为什么要使用(function(){})。call(this);?

时间:2013-09-23 22:43:31

标签: javascript

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

(function(undefined){
   /*(insert entire library here)*/
}).call(this);
这是什么意思?为什么这是编写库的好方法?

请注意,有时会忽略undefined,但我不知道将它放在那里有什么不同。我甚至不知道论据的来源,或来电者是谁。

1 个答案:

答案 0 :(得分:27)

让我们拆解这段代码。

首先,有一个匿名函数立即调用。它与此类似:

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

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


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

.callFunctions所有方法。第一个参数是this将被绑定的内容,后续参数将作为参数传递给函数。所以:

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

这与undefined一起使用(见下文)。

.call.apply相同,只有一个细微差别。 .apply只接受2个参数,其中第2个是参数数组。这将是类似的:

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

apply的常见用法是与magic变量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功能。我们借用Arrayslice函数,并使用.callthis设置为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 */
}());

这是完全有效的,并且工作原理相同。使用您发布的表单可能会有一些表现或利润。