传递成员时在 JavaScript 中丢失“this”上下文

IT技术 javascript
2021-01-22 03:48:31

在这里有一个简单的 JSFiddle演示我的问题。

我有这个 JavaScript 代码:

var b = document.getElementById("b");

function A() {
    this.f = "1";
}

A.prototype.t = function() {
    b.innerHTML = this.f;
};

var a = new A();

var l = a.t;
l();

为什么this当我尝试调用 at 时未定义?如何在不过度冗长或存储太多的情况下恢复该上下文?

3个回答

为什么当我尝试调用 at 时这是未定义的?

因为在 JavaScript 中,this主要取决于函数的调用方式,而不是定义它的位置。在调用中a.t()设置thisa,但l()设置thisundefined(在严格模式下)或全局对象(在松散模式下)。

更多(在我的博客上)

唯一的例外是“绑定”函数(与Function#bind)或 ES6 的“箭头”函数(this从定义它们的上下文中获取它们)。

如何在不过度冗长或存储太多的情况下恢复该上下文?

Function#bind 通常是一个很好的答案:

var l = a.t.bind(a);
l();

它返回一个新函数,当调用该函数时,将使用thisset调用原始函数为您提供的第一个参数bind(您也可以绑定其他参数。)这是一个 ES5 函数,但如果您需要支持非常旧的浏览器,您可以轻松地对它进行 polyfill。


如果您只需要使用特定调用 ,而不总是使用该值,正如Robert Rossmann 指出的那样,您可以使用or lthisFunction#callFunction#apply

l.call(this, 'a', 'b', 'c');    // Calls `l` with `this` set to `a` and args 'a', 'b', and 'c'
l.apply(this, ['a', 'b', 'c']); // Calls `l` with `this` set to `a` and args 'a', 'b', and 'c' -- note they're specified in an array
@RobertRossmann 你能证明一下吗?
2021-03-16 03:48:31
关于原始提问者的代码,如果A.t()在原始A函数中定义是否有效通过这种方式,该函数将能够访问私有范围的变量(像这样)。
2021-03-19 03:48:31
@eatonphil:l.call(a)将调用lthis设置为a
2021-03-23 03:48:31
@JeffNoel:是的。它不会是this,但是是的。然而,可能是“保留太多”。
2021-03-23 03:48:31
或者,Function.prototype.call如果函数不需要传递并且只需要调用一次,则可以使用var l = a.t; l.call(a);
2021-04-11 03:48:31

JavaScript 是功能范围的,

要为此执行具有正确值的函数,您需要将其绑定到正确的对象。例如,

var l= a.t.bind(a);
但是绑定上下文与范围并不真正相关。
2021-03-17 03:48:31

因为当您将函数分配给新变量时上下文会发生变化。你总是可以这样做a.t();