无法通过'this'访问属性

时间:2014-03-13 14:23:36

标签: javascript scope this private

在以下代码段中,我尝试从成员函数offset中访问属性shift()。看来,我无法以这种方式访问​​它,因为console.log报告了Offset: NaN

function shiftImg() {
  this.offset = 0;
  this.shift =
    function() {
      this.offset++;
      console.log("Offset: " + this.offset);
    };
}

productImg = new shiftImg;
window.setInterval(productImg.shift, 100);

然而,将上面的代码从模板范例转换为封闭范例的工作正如我所期望的那样:

function shiftImg() {
  var offset = 0;
  return {
    shift: function() {
      offset++;
      console.log("Offset: " + offset);
    }
  }
}

productImg = shiftImg();
window.setInterval(productImg.shift, 100);


在我的第一个示例中,为什么我无法通过运算符offset访问this


我的回答:
我会在这里发布我的解决方案,因为我不能附加一个独立的答案。 再次浏览可怕编写的MDN文档的混乱,我了解了bind方法:

function shiftImg() {
  this.offset = 0;
  this.shift =
    function() {
      this.offset++;
      var img = document.getElementById('img');
      img.style.paddingLeft = this.offset + 'px';
      console.log("Offset: " + this.offset);
    };
}

productImg = new shiftImg;
window.setInterval(productImg.shift.bind(productImg), 100);

2 个答案:

答案 0 :(得分:3)

嵌套函数没有自己的this上下文(它只是引用window),因此在this中为shiftImg方法指定一个变量您可以在嵌套函数中引用它:

function shiftImg() {
  var self = this;
  this.offset = 0;
  this.shift =
    function() {
      self.offset++;
      console.log("Offset: " + self.offset);
    };
}

productImg = new shiftImg();
window.setInterval(productImg.shift, 100);

您需要执行此操作的原因是因为调用该方法的setInterval调用在单独的执行上下文中运行,其中this等于window。如果您从this.shift()内拨打shiftImg(),则会看到您工作正常而无需添加selfSee this MDN article for more

或者,您将匿名函数传递给setInterval中的回调方法:

window.setInterval(function() {
    productImg.shift();
}, 100); 

如果你使用对象和jQuery,那么你会发现很多这个问题,而jQuery的$.proxy实用工具方法可以很容易地对上面做类似的事情。

答案 1 :(得分:0)

在第一个示例中,偏移量的上下文与shiftImage的上下文不同。第二个函数闭包改变了这个范围。