2012-04-23 207 views
2

我工作在JS一个相当复杂的对象上,我遇到了问题:JavaScript的嵌套的对象引用父

我有如下(有删节)代码:

var LocationSelector; 

LocationSelector = function(container) { 
    this.selectors = { 
    container: container, 
    city_name: container.find('input.city_name'), 
    city_id: container.find('input.city_id') 
    }; 
    return this.initialize(); 
}; 

LocationSelector.prototype = { 
    initialize: function() { 
    return this.city.checkStatus(); 
    }, 
    city: { 
    status: null, 
    message: null, 
    id: null, 
    checkStatus: function() { 
     if (LocationSelector.selectors.city_name.val() && LocationSelector.selectors.city_id.val()) { 
     return LocationSelector.city.setStatus('success'); 
     } 
    }, 
    setStatus: function(status) { 
     return alert(status); 
    } 
    } 
}; 

两个问题:

1)在子对象函数this中不再引用回根对象。如果我写出LocationSelector.object.method(args),似乎我可以参考父母,但这很重要。有没有办法将快捷方式定义回父对象?

2)在某些情况下,我需要每页有几个实例,所以对于我来说,当实例化一个新对象然后引用原型中的实例选择器时,我可以设置各种selectors。是指在子对象方法中的父对象(即LocationSelector)甚至可行吗? JS如何知道保持当前活动对象的存储属性?

基本上,我试图实现一个类,我对JS完全陌生,并不知道如何去做。所以,任何帮助或建议表示赞赏。谢谢!

回答

6

有很多事情错了你目​​前的做法。这里是更接近你想要的东西,但我不明白为什么LocationSelector实例有一个city成员。

function LocationSelector(container) { 
    this.selectors = { 
    container: container, 
    city_name: container.find("input.city_name"), 
    city_id: container.find("input.city_id") 
    }; 

    this.city = new City(this); 
    this.city.checkStatus(); 
} 

function City(locationSelector) { 
    this.status = null; 
    this.message = null; 
    this.id = null; 
    this.locationSelector = locationSelector; 
} 

City.prototype.checkStatus = function() { 
    if (this.locationSelector.selectors.city_name.val() && this.locationSelector.selectors.city_id.val()) { 
    this.setStatus("success"); 
    } 
}; 

City.prototype.setStatus = function() { 
    alert("status"); 
}; 

注意事项:

  1. 数据的属性去实例,而不是该原型。只有方法继续原型。
  2. City显然是它自己的类,所以你应该做到这一点。在你的代码中,一个城市在LocationSelector的所有实例之间被共享,因为它被放置在原型上。在此代码中,它在LocationSelector构造函数中被指定为实例属性。
  3. 您不能像您在示例中那样引用LocationSelector.selectorsLocationSelector.selectors将用于“静态”属性,其中LocationSelector不具有。相反,您需要参考特定实例上的selectors属性;在这个例子中,该实例由this.locationSelector给出。
  4. 要点2和3说明了一个重要事实:“子”City实例无法引用“父”LocationSelector类的属性,而没有具体的实例。

这里是一个让我更有意义,去除其中LocationSelectorcity特性(它不使用)的部分代码的版本。

function LocationSelectors(container) { 
    this.city_name = container.find("input.city_name"); 
    this.city_id = container.find("input.city_id"); 
} 

function City(locationSelectors) { 
    this.locationSelector = locationSelector; 
} 

City.prototype.checkStatus = function() { 
    if (this.locationSelectors.city_name.val() && this.locationSelectors.city_id.val()) { 
    this.setStatus("success"); 
    } 
}; 

City.prototype.setStatus = function() { 
    alert("status"); 
}; 

function checkCityStatus(container) { 
    var locationSelectors = new LocationSelectors(container); 
    var city = new City(locationSelectors); 

    city.checkStatus(); 
} 

我留给你一个链接到Crockford's "Private Members in JavaScript",其中谈到在JavaScript做OO。还有其他的,可能更好的解释,但至少那个会让你走上正轨。

+0

的原因城成员调用合适的范围是,此处理程序需要做一大堆的东西,所以在我原来使用大小写(每页只有一个处理程序)我发现创建它作为一个具有许多嵌套属性的对象字面值更容易,所以我可以做这样的事情:'LocationSelector.city.setStatus(...)'和'LocationSelector.district.changeName (...)'和'LocationSelector.errorMessages.display(...)'...等等。每个子对象都与DOM块相关,每个块都与其他块交互,而LocationSelector实际上就像是一个将它们绑定在一起的名称空间... – Andrew 2012-04-23 14:13:47

+0

...现在我有一种情况,我需要更多我不得不学习如何使用可以表现为不同实例的处理程序对象。当谈到JS时,我是一个全新的人,所以这真是我所知道的。无论如何,你的答案*非常有用,并显示我需要的东西:这两个基本补丁都显示了我的代码是如何被破坏的,并提供了一个更智能的方法的建议。非常感谢,如果我可以给你5个upvotes我会的。 – Andrew 2012-04-23 14:15:54

2

阅读关于Closures我很积极,你会找到你需要的。

这里的是你要完成的任务一个简单的例子:

function MyCoolObject(name){ 
    var self_myCoolObject = this; 
    this.name = name; 
    this.popAlertWithNameInFiveSeconds = function(){ 
     setTimeout(function(){ 
     alert('Incorrect reference to name "this.name" returns ' + this.name); 
     alert('Correct reference to name "self_myCoolObject.name" returns ' + self_myCoolObject.name); 
     },5000) 
    } 
} 

//TO TEST 
var MyObj = new MyCoolObject('MySuperCoolName') 
MyObj.popAlertWithNameInFiveSeconds(); 
0

这是我有的JS代码片段。在我拖入点击处理程序之前,我通过调用var parent = this来引用对象(SlideShow)。然后在以后的嵌套函数,你可以确保你使用parent.function()

/* Slide Show object */ 
function SlideShow(parentContainerId) { 

    this.BEGINNING = 'Beginning'; 
    this.END  = 'End of list'; 
    this.FIRSTINDEX = 0; 

    this.length  = jQuery(parentContainerId + ' img').length; 
    this.container = jQuery(parentContainerId); 
    this.imgs  = jQuery(parentContainerId + ' img'); 
    this.index  = this.FIRSTINDEX; 
    this.status  = 'beginning';   // beginning, end 



    this.init = function() { 
     // get it started 
     this.moveTo(this.FIRSTINDEX); 
     this.process(); 

     // ****GET OBJECT SCOPE***** 
     var parent  = this; 

     // set up click listener 
     this.container.find('img').click(function(e) { 
      var item_width = jQuery(this).width(); 
      var x_click_ps = e.clientX - jQuery(this).offset().left; 
      var x_diff  = x_click_ps/item_width; 




      console.log(this); 
      if (x_diff < .5) { 
       parent.moveByIncrement(-1) 
       parent.process(); 
      } else { 
       parent.moveByIncrement(1); 
       parent.process(); 
      } 

     }); 
    } 


. 
. 
. 
}