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

Mhm*_*z_A 10 javascript this comma-operator

谈话很便宜;给我看代码。

// equals to this.test = "inside window"
var test = "inside window";

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

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

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

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

我读过 ydkjs 的书,熟悉调用站点和动态this绑定,但我不明白为什么最后一个函数调用有window它的this上下文;在这个受控实验中,只有改变了()comma operator并且正如您在最后一条语句中看到的那样,comma operator正在做一些奇怪的事情。我怀疑它在返回值时会进行赋值(因为如果我们进行赋值会发生相同的结果),但我不确定。

Que*_*tin 9

鉴于:

foo.bar()
Run Code Online (Sandbox Code Playgroud)

里面barthisfoo

(也有例外,例如 whenbar是用箭头函数定义的,但它们不适用于这种情况)。

鉴于:

const bar = foo.bar;
bar();
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

  • 您是否可以将 `(1, a.fn)();` 视为 `(function(){ 1; return a.fn;}())();`?而 `(a.fn)();` 就变成了 `a.fn();`。 (2认同)
  • @Leonardo `(a.fn)` 没有逗号运算符,它只是 `a.fn`,括号不会引起评估 (2认同)

Abh*_*yer 6

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

只有在使用对象调用应用/调用函数时,它才能获得上下文。

(1, a.fn).call(a); // "object"
(1, a.fn).apply(a); // "object"
Run Code Online (Sandbox Code Playgroud)