使用'self'

时间:2017-11-15 19:31:57

标签: javascript

似乎javascript范围不正确。它看起来不像正常的范围问题,因为使用.call()或.bind()仍会导致错误的范围。具体的代码使用Knockout和LoDash,但我不认为这两个库都与这个bug有关。核心代码元素如下:

var FacilityDisplayModel = function (facility, options) {
   var self = facility ? facility : this;  
   self.Areas = ko.observableArray();
   ...
   self.hydrate = function (facilityHierarchy)
   {
      ...
      var areas = facilityHierarchy.Areas()
      for (var i in areas)
      {
	      new AreaDisplayModel(areas[i], self, options);
      }
      self.Areas(areas);
      ...
   }

   self.hydrateHasCars = function(trackListWithoutCars){
     var hasCars = false;
     _.forEach(self.Areas(), function (area) {
        if(area.hydrateHasCars(trackListWithoutCars)) hasCars = true;
     });
     ...
   }
   return self;
}

var AreaBaseModel = function (area, parent, options) {
   var self = area ? area : this;
   if (self.Areas) {
      for (var i in self.Areas()) {
          new AreaDisplayModel(self.Areas()[i], self, options);
      }
   }
   ...
   return self;
}

var AreaDisplayModel = function (area, parent, options) {
    self = new AreaBaseModel(area, parent, options);
    self.Name;

    self.hydrateHasCars = function(trackListWithoutCars) {
        var hasCars = false;
        _.forEach(self.Areas(), function(area) {
            if (area.hydrateHasCars(trackListWithoutCars)) hasCars = true;
        });
    }
    ...
    return self;
}

这个问题是使用.call()或作为普通函数调用.hydrateHasCars()会导致结果的范围错误。它最终使用当前实例范围而不是子范围。

例如,我们所在的区域名称为“区域1”。当我们通过区域前进时,第一个区域被称为“区域1.1”。这是同一对象的单独实例。但是在“区域1.1”上调用.hydrateHasCars()会导致“区域1”的自我。即使使用.call(area,...),特别是将范围设置为“Area 1.1”,它仍然会产生“区域1”的“自我”范围。

编辑:我已更新代码段以包含更多代码。我已尽可能多地考虑可能与此问题相关。代码流是这样的:一个设施用来自服务器的信息,建立区域,下面有子区域。然后,我们从服务器获取汽车信息并浏览这些区域,进行更新。我们需要知道子区域是否有汽车才能知道它的父区是否有汽车。这里是范围问题,其中父区域调用子区域,但是在调试时,我可以看到调用中的“self”是指父级而不是子级。

我发现的解决方法是将hydrateHasCars视为“静态”并传递到以下区域:

self.hydrateHasCars = function(parentArea, trackListWithoutCars) {
    var hasCars = false;
    _.forEach(parentArea.Areas(), function(area) {
        if (area.hydrateHasCars(area, trackListWithoutCars)) hasCars = true;
    });
};

但是,我宁愿使用非“静态”方法并修复范围问题。

0 个答案:

没有答案