JavaScript嵌套对象父对象的引用

时间:2012-04-23 03:28:42

标签: javascript object prototype

我正在研究JS中一个相当复杂的对象,我遇到了问题:

我有以下(删节)代码:

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完全不熟悉并且不知道该怎么做。所以,任何帮助或建议都表示赞赏。谢谢!

3 个答案:

答案 0 :(得分: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点说明了一个重要的事实:“child”City实例在没有具体实例的情况下无法引用“父”LocationSelector类的属性。

  5. 以下是对我更有意义的代码版本,删除LocationSelector具有city属性(不使用)的部分。

    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。还有其他可能更好的解释,但至少那一个会让你走上正轨。

答案 1 :(得分: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();

答案 2 :(得分:0)

这是我所拥有的JS代码片段。在我进入点击处理程序之前,我通过调用SlideShow来引用对象(var parent = this)。然后在以后的嵌套函数中,您可以确保使用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();
            }

        });
    }


.
.
.
}