为什么逗号运算符会在函数调用中更改“ this”

问题描述

对话很便宜;给我看代码

// equals to this.fellan = "window"
var fellan = "window";

function f () {
  console.log(this.fellan)
};

var a = {
  fellan: "object",fn: f
};

a.fn(); // "object"   --> fine
(a).fn(); // "object"   --> fine
(1,a).fn(); // "object"   --> fine
(a.fn)(); // "object"   --> fine
(1,a.fn)(); // "window"   --> why?

// reference equality check
console.log(
  f === a.fn && 
  (a.fn) === f && 
  f === (1,a.fn)
); // all equal :/

我已经读过ydkjs书籍,并且对调用站点和动态this绑定非常熟悉,但是我不明白为什么最后一个函数调用window作为其this上下文;在这个对照实验中,只有一件事 ()comma operator发生了变化,正如您在上一条语句中看到的comma operator所做的一样奇怪。我怀疑它在返回值时会执行赋值操作(因为如果执行赋值操作,则会发生相同的结果),但是我不确定。

解决方法

给出:

foo.bar()

bar内,this将是foo

(有一些例外,例如使用箭头功能定义了bar时,但在这种情况下不适用)。

给出:

const bar = foo.bar;
bar();

现在已在没有foo上下文的情况下调用了该函数,因此this现在是默认对象(在浏览器中为window)。

表达式:(1,foo.bar)的计算结果为右侧。这就是功能。

就像您已将其复制到变量一样,这在您调用函数之前将函数与对象断开连接,因此您获得相同的效果。

没有赋值是因为您没有涉及变量,而是您在调用表达式的结果而不是直接调用对象方法。

,

为支持@Quentin的答案,逗号运算符的确将最后一个操作数作为没有上下文的函数(因此窗口)而不是对象蓝图中的那个返回。

仅在使用对象调用函数的apply / call时,它才能获取上下文。

(1,a.fn).call(a); // "object"
(1,a.fn).apply(a); // "object"