JavaScript:在调用之前将函数重新分配给局部变量,而不是直接调用并对'这'

JavaScript: Reassignment of function to local variable prior to calling vs. just calling directly and subsequent effects on 'this'

本文关键字:调用 局部变量 函数 分配 JavaScript 新分配      更新时间:2023-09-26

考虑这个例子:

function Dummy(buddy) {
    this._buddy = buddy;
}
Dummy.prototype.greetBuddy = function() {
    console.log('Hello, '+this._buddy);
}
function outerGreet1(dummy) {
    var func = dummy.greetBuddy;
    func();
}
function outerGreet2(dummy) {
    dummy.greetBuddy();
}

可以说,这并不能传达我为什么要这么做,而是我所遇到的事情的基本升华。我刚刚修复了我的程序中由于这种区别而产生的一个错误。outerGreet1将抛出一个错误,因为它找不到它_buddy,而outerGreet2将打印预期结果。

为了代码清晰,我只是将函数复制到一个局部变量中,但显然这对我来说是一次成熟的学习经验。这里到底发生了什么?我猜"this"最终指的是outerGreet1函数?我来自Java,所以我知道JavaScript只有函数范围,但为什么创建对函数的新引用会改变它的行为?我的印象是"这"与当前的范围相对应,我不确定重新分配是如何改变范围的,所以我的理解在某个地方有缺陷。

如果这是一个常见的JavaScript问题,我很抱歉,但我在搜索时遇到了很大的困难,无法找到任何答案。

this变量取决于函数的使用方式。

如果实例化函数(将其视为类),则this将引用类的实例:

new outerGreet1(dummy); // `this` is an instance of outerGreet1

如果用Function.prototype.call调用它,那么this将引用您传递给call方法的任何对象:

outerGreet1.call(anotherObjec, dummy); // `this` refers to anotherObject

如果您只是直接执行它,那么this可能会引用窗口或任何其他周围的范围。

outerGreet1(dummy); // `this` likely refers to the window object

您还可以使用Function.prototype.bind将您的函数封装在特定的范围内,以帮助清理:

var wrappedExample = outerGreet1.bind(aSpecificObject);
wrappedExample(dummy); // Doesn't matter how it's called, `this` will refer to aSpecificObject

当然,在使用bind(或使用polyfill)之前,您可能需要考虑您的目标浏览器。