28

我最近一直在研究一些 JS 库,这些库是由真正知道自己在做什么的人编写的,我一直看到这种模式,但我找不到有关它的信息。我阅读了有关 .call() 方法的文档,但这对我来说并没有什么意义。我希望通过示例获得那些经典的深入 SO 解释之一。

(function(undefined){
   /*(insert entire library here)*/
}).call(this);

这是关于什么的?为什么这是编写库的好方法?

请注意,有时undefined省略了,尽管我不知道将它放在那里有什么区别。我什至不知道这些论点来自哪里,或者调用者是谁。

4

1 回答 1

28

让我们反汇编这段代码。

首先有一个带有立即调用的匿名函数。它类似于:

(function () {/**/}).call();
(new Date()).getTime(); // timestamp since 1970 jan 1 in milliseconds

我们不分配new Date()给变量,而是立即使用它。


现在为什么要使用.call而不是 just ()

.call是一种方法Functions都有。第一个参数是this绑定的对象,后续参数将作为参数传递给函数。所以:

(function () {
    console.log(this.foo); // bar
}).call({ "foo": "bar" });

这与undefined(见下文)结合使用。

.call与一个微小的区别相同只需要 2 个参数,其中第二个是参数数组。这将是类似的:.apply.apply

(function () {}).call(this, "foo", "bar");
(function () {}).apply(this, [ "foo", "bar" ]);

apply 的一个常见用途是与魔法变量结合使用arguments

(function () {
     console.log(Array.prototype.slice.call(arguments, 1)); // [ "bar" ]
})([ "foo", "bar" ]);

Array.prototype.slice.call(arguments, 1)可能看起来很吓人,但实际上它只是arguments.slice(1),但arguments不是,Array所以它没有slice功能。我们借用Arraysslice函数并使用.call来设置thisto argumentsArray.prototype.slice(arguments, 1??)是不正确的。


现在为什么在this里面.call(this)this总是指向您所在的上下文。如果您在一个类的实例中,它将指向该实例,如果您在全局范围内,它将指向该实例。在浏览器环境中也是window.


为什么undefined?由于我们.call(this)没有第二个参数,所以匿名函数的所有参数都是undefined. 我不太确定为什么需要在此处创建一个显式变量undefined。也许这是对某些浏览器或某些喜欢undefined定义的 lint 工具的支持。

感谢@TedHopp。undefined善变。

var undefined = "foo";
console.log(undefined); // undefined

(function (undefined) {
    console.log(undefined); // "foo"
})("foo");

您可以轻松拥有:

(function () {
    /* code here */
}());

这是完全有效的,并且工作方式相同。使用您发布的表单可能会有一些性能或 linting 好处。

于 2013-09-23T23:05:34.497 回答