您混淆了范围和上下文。第一个对于给定函数是固定的(除非它由某个函数返回,有效地被注入到外部作用域中),第二个(其中定义了this
在这个函数内部引用的内容)在函数被调用时被赋予- 实际上可以用call
和改变apply
。
考虑一下:
var someObj = function() {
var internalObj = {
nam: 'internal',
doSomething: function() {
console.log('Called from ' + this.name);
}
}
internalObj.doSomething('Internal'); // 1
var someFunc = internalObj.doSomething;
someFunc(); // 2
return {
nam: 'external',
doSomething: internalObj.doSomething
}
}
var x = new someObj();
x.doSomething(); // 3
setTimeout(x.doSomething, 1000); // 4
setTimeout(x.doSomething.bind({nam:'a new one'}), 2000); // 5
JSF中。
在这个例子中,我们将方法 'doSomething' 定义为internalObj
变量的属性,它是这个构造函数的本地属性——如果你试图在外部访问它someObj
,你会得到 ReferenceError。
当在构造函数本身 (1) 中调用方法时,您将记录“从内部调用” - 正如方法的上下文对象 ( this
) 现在所指的那样internalObj
。
当我们将此方法(其引用)分配给另一个局部变量并从那里调用它时(2),“未定义”被记录下来。Scope 在这里显然没有改变,但是上下文变量改变了:它现在引用了全局对象。
然后我们将这个方法作为构造函数的结果返回 - 事情开始变得更加有趣:我们的函数现在在外部范围内可用!但请注意,(3) 和 (4) 中其调用结果之间的差异:前者给了我们external
(因为这里的上下文对象是由构造函数创建的),后者再次返回我们,undefined
即使语法是一样的。) 发生这种情况是因为发送到超时和事件处理程序的函数“丢失”了它们的上下文,简而言之......除非我们用Function.prototype.bind
方法修复它,就像在 (5) 中一样。