Javascript在分配给其他变量时丢失了上下文

时间:2014-04-18 13:04:55

标签: javascript this

为什么在javascript中如果将对象方法引用到某个变量,则会丢失该对象上下文。无法找到任何链接,解释引擎盖下发生的事情。除了这个说明:   ‘this’ refers to the object which ‘owns’ the method这不是真的。

var Class = function() {
    this.property = 1
}

Class.prototype.method = function() {
    return this.property;
}

var obj = new Class();
console.log(obj.method() === 1);

var refToMethod = obj.method; // why refToMethod 'this' is window


console.log(refToMethod() !== 1) // why this is true?

var property = 1;
console.log(refToMethod() === 1)

4 个答案:

答案 0 :(得分:2)

这取决于函数的调用方式。如果函数不是通过作为对象的属性来引用的(例如refToMethod)那么它将被分配"全局上下文"这是window。但是,当一个函数是一个对象的属性(例如obj.method)时,我们将它称为一个方法,并且它被隐式地赋予它的父对象的上下文。

JavaScript的上下文与许多语言不同,您可以使用.call().apply()轻松覆盖它。此外,ECMAScript 5引入了一个新的.bind()方法,允许您创建始终绑定到同一上下文的方法的副本。 See MDN for more

var obj = new Class();
obj.method(); // 1;

var unbound = obj.method;
unbound(); // undefined;

// Call and Apply setting the context to obj.
unbound.apply(obj); // 1
unbound.call(obj); // 1;

// ECMAScript 5's bind
var bound = unbound.bind(obj);
bound(); // 1;

答案 1 :(得分:1)

来自Douglas Crockford的书JavaScript: The Good Parts

  

这个参数在面向对象编程中非常重要,   它的值由调用模式决定。有四个   JavaScript中的调用模式:方法调用模式,   函数调用模式,构造函数调用模式,   和apply调用模式。奖金的方式不同   参数this is initialized

方法调用模式

  

当函数存储为对象的属性时,我们将其称为a   方法。调用方法时,它绑定到该对象。如果   调用表达式包含一个细化(即。点   表达式或[下标]表达式),它被调用为方法

在您的示例中,方法调用模式为

console.log(obj.method() === 1);

并且在这种情况下绑定到对象" Class"它按预期工作。

函数调用模式

  

当函数不是对象的属性时,则调用它   作为一个功能:

     

var sum = add(3,4); //总和是7

     

使用此模式调用函数时,将绑定到该函数   全球对象。这是语言设计中的一个错误。有   当内部函数是,语言设计正确   在调用时,这仍将绑定到外部的this变量   功能。这种错误的结果是方法无法使用   一个内部函数,因为内部函数帮助它完成它的工作   不会共享方法对该对象的访问权限,因为它受到绑定   错误的值

在你的情况下

var refToMethod = obj.method; // why refToMethod 'this' is window
console.log(refToMethod() !== 1) // why this is true?

refToMethod绑定到全局对象" window"在这种情况下

您可以在JavaScript “this” keyword

找到有关此内容的更多信息

答案 2 :(得分:0)

因为您只将method功能分配给refToMethod。运行时,上下文为window

答案 3 :(得分:0)

当您打印对象和对函数的引用时,它变得清晰:

console.log(obj); // Prints -> Class {property: 1, method: function}

console.log(refToMethod);
// Prints 
// function () {
//    return this.property;
// }

obj的上下文中,this是什么?它是Class对象,具有名为property的属性。

this的上下文中refToMethod是什么?它是window对象。这就是为什么你的断言第一次失败,第二次是真的。当你声明:

var property = 1;

您实际上是在声明window对象的属性。