我一直在写javascript一段时间,最近一直在玩coffeescript。我注意到coffeescript以下列方式编译函数:
(function() {
}).call()
我也注意到人们以这种方式写函数:
(function() {
})()
据我所知,这些是自称的匿名函数。首先,.call()
与()
.call()
之间的区别在于()
只是一种更为语义的写作方式{{1}}。
另外,为什么coffeescript将整个文件包装在匿名函数中,而通常不需要?这有什么表现或其他优势吗?应该何时使用这些自调用函数?
由于
答案 0 :(得分:5)
使用.call()
将IIFE的上下文更改为父作用域的this
值。
第一个this
将是[object Window]
,浏览器环境中的全局范围:
(function () {
console.log(this);
})();
第二个,将完全相同:
(function () {
console.log(this);
}).call(this);
区别在于ECMAScript 5的strict mode
,第一个示例this
将是未定义的:
(function () {
'use strict';
console.log(this); // undefined
})();
但是,当使用严格模式和 .call()时,这又是具有正确this
上下文的全局范围:
(function () {
'use strict';
console.log(this);
}).call(this);
Here's a jsFiddle显示了这一点。主要区别在于normal
IIFE丢失了this
上下文,一些CommonJS平台评估具有特定this
的文件。
CoffeeScript这样做是为了确保您的代码与放置它的作用域(父作用域)具有相同的this
上下文 - 因为函数通常不会从周围的上下文继承它们的this
对象
使用上面的模式,您应该将函数逻辑包装在那里,以避免将所有代码放在全局范围内并且具有变量/命名冲突,然后您可以创建诸如模块之类的东西并仅返回您需要的API,例如:
var Module = (function () {
'use strict';
return {
someMethod: function () {
// do something
}
}
})();
// call it:
Module.someMethod();
每个函数都创建自己的范围,因此将代码块包装在其中将保护您的变量/函数名称不会相互冲突。我们还可以从这些闭包中访问“私有”方法:
var Module = (function () {
'use strict';
var _privateMethod = function () {};
return {
someMethod: function () {
_privateMethod();
}
}
})();
当我们不希望我们的用户也可以公开访问这些方法时,我们会这样做。