我有一个注册事件处理程序的构造函数:

函数MyConstructor(数据,传输){this.data=数据;transport.on('数据',函数(){警报(this.data);});}//模拟传输对象var传输={on:函数(事件,回调){setTimeout(回调,1000);}};//称为var obj=新MyConstructor('o',传输);

但是,我无法访问回调中创建的对象的数据属性。看起来这不是指创建的对象,而是指另一个对象。

我还尝试使用对象方法而不是匿名函数:

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', this.alert);
}

MyConstructor.prototype.alert = function() {
    alert(this.name);
};

但它表现出相同的问题。

如何访问正确的对象?


当前回答

我们不能将其绑定到setTimeout(),因为它总是使用全局对象(Window)执行。如果您想在回调函数中访问this上下文,那么通过对回调函数使用bind(),我们可以如下实现:

setTimeout(function(){
    this.methodName();
}.bind(this), 2000);

其他回答

我遇到了Ngx折线图xAxisTickFormatting函数的问题,该函数是从HTML调用的,如下所示:[xAxisTikFormatting]=“xFormat”。

我无法从声明的函数访问组件的变量。这个解决方案帮助我解决了问题,找到了正确的答案。

不要像这样使用函数:

xFormat (value): string {
  return value.toString() + this.oneComponentVariable; //gives wrong result
}

使用此项:

 xFormat = (value) => {
   // console.log(this);
   // now you have access to your component variables
   return value + this.oneComponentVariable
 }

目前,如果在代码中使用类,还有另一种可能的方法。

有了类字段的支持,可以通过以下方式实现:

class someView {
    onSomeInputKeyUp = (event) => {
        console.log(this); // This refers to the correct value
    // ....
    someInitMethod() {
        //...
        someInput.addEventListener('input', this.onSomeInputKeyUp)

当然,在幕后,绑定上下文的都是旧的好箭头函数,但在这种形式下,它看起来比显式绑定更清楚。

由于这是一个第3阶段的提案,您需要Babel和适当的Babel插件来处理它(08/2018)。

另一种方法是EventListener接口中的handleEvent(evt)方法,这是自DOM2以来将其绑定到事件侦听器中的标准方法,它允许您始终删除侦听器(以及其他好处):

var obj = {
  handleEvent(e) {
    // always true
    console.log(this === obj);
  }
};

document.body.addEventListener('click', obj);

有关使用handleEvent的详细信息可以在以下位置找到:DOM handleEvent:自2000年以来的跨平台标准

这一切都在调用方法的“神奇”语法中:

object.property();

当您从对象中获取属性并一次性调用它时,该对象将成为该方法的上下文。如果调用相同的方法,但在不同的步骤中,则上下文是全局范围(窗口):

var f = object.property;
f();

当您获得方法的引用时,它将不再附加到对象。它只是对普通函数的引用。当您获取要用作回调的引用时,也会发生同样的情况:

this.saveNextLevelData(this.setAll);

这就是将上下文绑定到函数的地方:

this.saveNextLevelData(this.setAll.bind(this));

如果使用jQuery,则应改用$.proxy方法,因为并非所有浏览器都支持绑定:

this.saveNextLevelData($.proxy(this.setAll, this));

以下是访问子上下文中的父上下文的几种方法-

您可以使用bind()函数。在另一个变量中存储对context/this的引用(参见下面的示例)。使用ES6箭头功能。改变代码、功能设计和架构——为此,您应该能够控制JavaScript中的设计模式。

1.使用bind()函数

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', ( function () {
        alert(this.data);
    }).bind(this) );
}
// Mock transport object
var transport = {
    on: function(event, callback) {
        setTimeout(callback, 1000);
    }
};
// called as
var obj = new MyConstructor('foo', transport);

如果您正在使用Undercore.js-http://underscorejs.org/#bind

transport.on('data', _.bind(function () {
    alert(this.data);
}, this));

2.在另一个变量中存储对context/this的引用

function MyConstructor(data, transport) {
  var self = this;
  this.data = data;
  transport.on('data', function() {
    alert(self.data);
  });
}

3.箭头功能

function MyConstructor(data, transport) {
  this.data = data;
  transport.on('data', () => {
    alert(this.data);
  });
}