JavaScript 函数调用脱糖

JavaScript function call desugar

我发现 this 文章说 JavaScript 函数调用实际上只是 func.call(...) 的语法糖。

我想问一下这是不是真的,因为我在规范中没有找到类似的内容(还没有真正彻底检查过,只是简单浏览并搜索 call() 这个词) .

如果有人能开导我就太好了,因为如果这篇文章是真的,我对 EcmaScript 语言的钦佩可能会减少。

我明白为什么文章会这么说,而且在某种程度上是这样。

他们声称的原因可能是因为直接使用的函数是未绑定的,这意味着如果我创建一个对象:

const a = { say: function() { console.log(this.message) } };
a.message = 'hello';
a.say();

当我运行函数a.say()时,say()中的this上下文是a。那相当于 a.say.call(a).

因为我没有显式绑定那个函数,如果我把它传递到其他地方可以调用它,它就不一定再有 a 的上下文了:

const a = { say: function() { console.log(this.message) } };
const b = {};
a.message = 'hello';
b.message = 'goodbye';
b.say = a.say;
b.say();

请注意,即使我复制了 asay(),当使用 b 调用时,它最终还是使用 b 调用,因为它是上下文(this).因此,它本质上等同于 a.say.call(b).

如果您显式绑定函数,那么它将始终使用固定的上下文:

const a = { say: function() { console.log(this.message); } };
const b = {};
a.message = 'hello';
b.message = 'goodbye';
b.say = a.say.bind(a);
b.say();

绑定后,它现在将始终使用 a 的上下文,即使我可能会将函数传递到其他地方。

话虽如此,我不确定为什么您的钦佩会受到影响。实际上,我发现这是该语言的一个很棒的特性,它使它非常强大和灵活。它允许你做这样的事情:

Array.prototype.slice.call(document.querySelectorAll('div'))
  .forEach(el => console.log(el.innerHTML));
<div>A</div>
<div>B</div>
<div>C</div>

在那个例子中,document.querySelectorAll() returns a NodeList,通常没有 forEach()。但是,由于它足够兼容,我可以使用 call() 将其传递给 Array.prototype.slice 以将其转换为具有这些元素的 Array。 (你也可以直接把它给forEach(),但我更喜欢用slice()转换它然后做进一步的事情。)

The [[Call]] internal method of every function is activated when we call a function (via the call expression, e.g. foo() or with using call and apply methods).

~ Dmitry Soshnikov, article 关于 .bind


Internal Properties Only Defined for Some Objects

Internal Property - [[Call]]

Description - Executes code associated with the object. Invoked via a function call expression. The arguments are a this object and a list containing the arguments passed to the function call expression. Objects that implement this internal method are callable.

~ 请参阅 Table 9 here at 带注释的 ECMAScript 5.1
另见 13.2 Creating Function Objects13.2.1 [[Call]]
绑定 15.3.4.5, 15.3.4.5.1,5 [[Call]]

那里定义的所有步骤当然只是内部步骤,因此不会发生实际的“脱糖”转换,但这些内部步骤确实 DO 类似。


tl;博士

我猜,简而言之,你可以把他在文章中说的想成

How to mimick what's going on under the roof to better understand the concept.