为什么在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)
答案 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"在这种情况下
找到有关此内容的更多信息答案 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
对象的属性。