Javascript 如何在回调中访问正确的'this'?

Javascript 如何在回调中访问正确的'this'?,javascript,callback,this,Javascript,Callback,This,我有一个注册事件处理程序的构造函数: 函数MyConstructor(数据、传输){ 这个数据=数据; transport.on('data',function(){ 警报(此数据); }); } //模拟传输对象 var传输={ on:函数(事件、回调){ setTimeout(回调,1000); } }; //称为 var obj=新的MyConstructor('foo',transport)关于此 此(又称“上下文”)是每个函数中的一个特殊关键字,其值仅取决于函数的调用方式,而不是函数

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

函数MyConstructor(数据、传输){
这个数据=数据;
transport.on('data',function(){
警报(此数据);
});
}
//模拟传输对象
var传输={
on:函数(事件、回调){
setTimeout(回调,1000);
}
};
//称为
var obj=新的MyConstructor('foo',transport)关于
(又称“上下文”)是每个函数中的一个特殊关键字,其值仅取决于函数的调用方式,而不是函数的定义方式/时间/地点。与其他变量一样,它不受词法范围的影响(箭头函数除外,见下文)。以下是一些例子:

function foo() {
    console.log(this);
}

// normal function call
foo(); // `this` will refer to `window`

// as object method
var obj = {bar: foo};
obj.bar(); // `this` will refer to `obj`

// as constructor function
new foo(); // `this` will refer to an object that inherits from `foo.prototype`
要了解有关此
的更多信息,请查看


如何引用正确的

使用
ECMAScript 6引入了箭头函数,可以将其视为lambda函数。他们没有自己的
绑定。相反,
这个
像普通变量一样在范围内查找。这意味着您不必调用
.bind
。这不是他们唯一的特殊行为,更多信息请参考MDN文档

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', () => alert(this.data));
}
不要使用
实际上,您不想访问此
,尤其是它所指的对象。这就是为什么一个简单的解决方案是创建一个新的变量,该变量也引用该对象。变量可以有任何名称,但常见的名称是
self
that

function MyConstructor(data, transport) {
    this.data = data;
    var self = this;
    transport.on('data', function() {
        alert(self.data);
    });
}
由于
self
是一个普通变量,因此它遵守词法范围规则,并且可以在回调中访问。这还有一个优点,即您可以访问回调本身的
This

显式设置回调的
-第1部分 您可能无法控制此
的值,因为它的值是自动设置的,但事实并非如此

每个函数都有一个方法,该方法返回一个新函数,并将
this
绑定到一个值。该函数的行为与您调用的
.bind
on函数完全相同,只是
由您设置。无论如何或何时调用该函数,
将始终引用传递的值

function MyConstructor(data, transport) {
    this.data = data;
    var boundFunction = (function() { // parenthesis are not necessary
        alert(this.data);             // but might improve readability
    }).bind(this); // <- here we are calling `.bind()` 
    transport.on('data', boundFunction);
}
第一个参数是回调,第二个参数是这个
应该引用的值。下面是一个人为的例子:

var arr = [1, 2, 3];
var obj = {multiplier: 42};

var new_arr = arr.map(function(v) {
    return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument
函数
this.method
被指定为click事件处理程序,但如果单击
document.body
,则记录的值将
未定义
,因为在事件处理程序中,
指的是
document.body
,而不是
Foo
的实例
如前所述,此所指的内容取决于函数的调用方式,而不是定义方式 如果代码如下所示,则函数没有对对象的隐式引用可能更为明显:

function method() {
    console.log(this.data);
}


function Foo() {
    this.data = 42,
    document.body.onclick = this.method;
}

Foo.prototype.method = method;
解决方案与上述相同:如果可用,请使用
.bind
显式绑定到特定值

document.body.onclick = this.method.bind(this);
或者使用匿名函数作为回调/事件处理程序显式调用函数作为对象的“方法”,并将对象(
this
)分配给另一个变量:

var self = this;
document.body.onclick = function() {
    self.method();
};
或使用箭头功能:

document.body.onclick = () => this.method();
this.saveNextLevelData(this.setAll.bind(this));
关于
(又称“上下文”)是每个函数中的一个特殊关键字,其值仅取决于函数的调用方式,而不是函数的定义方式/时间/地点。与其他变量一样,它不受词法范围的影响(箭头函数除外,见下文)。以下是一些例子:

function foo() {
    console.log(this);
}

// normal function call
foo(); // `this` will refer to `window`

// as object method
var obj = {bar: foo};
obj.bar(); // `this` will refer to `obj`

// as constructor function
new foo(); // `this` will refer to an object that inherits from `foo.prototype`
要了解有关此的更多信息,请查看


如何引用正确的

使用
ECMAScript 6引入了箭头函数,可以将其视为lambda函数。他们没有自己的
绑定。相反,
这个
像普通变量一样在范围内查找。这意味着您不必调用
.bind
。这不是他们唯一的特殊行为,更多信息请参考MDN文档

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', () => alert(this.data));
}
不要使用
实际上,您不想访问此
,尤其是它所指的对象。这就是为什么一个简单的解决方案是创建一个新的变量,该变量也引用该对象。变量可以有任何名称,但常见的名称是
self
that

function MyConstructor(data, transport) {
    this.data = data;
    var self = this;
    transport.on('data', function() {
        alert(self.data);
    });
}
由于
self
是一个普通变量,因此它遵守词法范围规则,并且可以在回调中访问。这还有一个优点,即您可以访问回调本身的
This

显式设置回调的
-第1部分 您可能无法控制此
的值,因为它的值是自动设置的,但事实并非如此

每个函数都有一个方法,该方法返回一个新函数,并将
this
绑定到一个值。该函数的行为与您调用的
.bind
on函数完全相同,只是
由您设置。无论如何或何时调用该函数,
将始终引用传递的值

function MyConstructor(data, transport) {
    this.data = data;
    var boundFunction = (function() { // parenthesis are not necessary
        alert(this.data);             // but might improve readability
    }).bind(this); // <- here we are calling `.bind()` 
    transport.on('data', boundFunction);
}
第一个参数是回调,第二个参数是这个
应该引用的值。下面是一个人为的例子:

var arr = [1, 2, 3];
var obj = {multiplier: 42};

var new_arr = arr.map(function(v) {
    return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument
函数
this.method
被指定为click事件处理程序,但如果单击
document.body
,则记录的值将
未定义
,因为在事件处理程序中,
指的是
document.body
,而不是
Foo
的实例
如前所述
this.saveNextLevelData($.proxy(this.setAll, this));
transport.on('data', _.bind(function () {
    alert(this.data);
}, this));
there are two types of scope in javascript. They are :

   1) Global Scope

   2) Function Scope
--------------------------------------------------------------------------------
-                                                                              -
-   Global Scope                                                               -
-   ( globally "this" refers to window object)                                 -     
-                                                                              -
-         function outer_function(callback){                                   -
-                                                                              -
-               // outer function scope                                        -
-               // inside outer function"this" keyword refers to window object -                                                                              -
-              callback() // "this" inside callback also refers window object  -

-         }                                                                    -
-                                                                              -
-         function callback_function(){                                        -
-                                                                              -
-                //  function to be passed as callback                         -
-                                                                              -
-                // here "THIS" refers to window object also                   -
-                                                                              -
-         }                                                                    -
-                                                                              -
-         outer_function(callback_function)                                    -
-         // invoke with callback                                              -
--------------------------------------------------------------------------------
function Person(name){

    this.name = name

    this.sayNameVersion1 = function(callback){
        callback.bind(this)()
    }
    this.sayNameVersion2 = function(callback){
        callback()
    }

    this.sayNameVersion3 = function(callback){
        callback.call(this)
    }

    this.sayNameVersion4 = function(callback){
        callback.apply(this)
    }

}

function niceCallback(){

    // function to be used as callback

    var parentObject = this

    console.log(parentObject)

}
var p1 = new Person('zami') // create an instance of Person constructor
this.sayNameVersion1 = function(callback){
    callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
    callback()
}
p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method

p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback
this.sayNameVersion3 = function(callback){
    callback.call(this)
}
p1.sayNameVersion3(niceCallback)
this.sayNameVersion4 = function(callback){
    callback.apply(this)
}
p1.sayNameVersion4(niceCallback)
setTimeout(function(){
    this.methodName();
}.bind(this), 2000);
var obj = {
  handleEvent(e) {
    // always true
    console.log(this === obj);
  }
};

document.body.addEventListener('click', obj);
class someView {
    onSomeInputKeyUp = (event) => {
        console.log(this); // this refers to correct value
    // ....
    someInitMethod() {
        //...
        someInput.addEventListener('input', this.onSomeInputKeyUp)
function MyConstructor(data, transport) {
    this.data = data;
    var self = this;
    transport.on('data', function () {
        alert(self.data);
    });
}
  function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data',()=> {
        alert(this.data);
    });
}
  function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data',(function() {
        alert(this.data);
    }).bind(this);
function MyConstructor(data, transport) {
  this.data = data;
  transport.on('data', () => {
    alert(this.data);
  });
}
module.exports.data = 'module data';
// This outside a function in node refers to module.exports object
console.log(this);

const obj1 = {
    data: "obj1 data",
    met1: function () {
        console.log(this.data);
    },
    met2: () => {
        console.log(this.data);
    },
};

const obj2 = {
    data: "obj2 data",
    test1: function () {
        console.log(this.data);
    },
    test2: function () {
        console.log(this.data);
    }.bind(obj1),
    test3: obj1.met1,
    test4: obj1.met2,
};

obj2.test1();
obj2.test2();
obj2.test3();
obj2.test4();
obj1.met1.call(obj2);
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
 }