我最近一直在研究一些JS库,这些库是由真正知道自己在做什么的人编写的,我一直看到这种模式,而且我找不到有关它的信息。我阅读了.call()方法的文档,但它对我来说并没有多大意义。我希望通过实例获得其中一个经典的深入SO解释。
(function(undefined){
/*(insert entire library here)*/
}).call(this);
这是什么意思?为什么这是编写库的好方法?
请注意,有时会忽略undefined
,但我不知道将它放在那里有什么不同。我甚至不知道论据的来源,或来电者是谁。
答案 0 :(得分:27)
让我们拆解这段代码。
首先,有一个匿名函数立即调用。它与此类似:
(function () {/**/}).call();
(new Date()).getTime(); // timestamp since 1970 jan 1 in milliseconds
我们不会将new Date()
分配给变量,而是立即使用它。
现在为什么要使用.call
而不只是()
?
.call
是Functions
所有方法。第一个参数是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
功能。我们借用Array
个slice
函数,并使用.call
将this
设置为arguments
。 Array.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 */
}());
这是完全有效的,并且工作原理相同。使用您发布的表单可能会有一些表现或利润。