【问题标题】:Brackets wrapping of functions - (function() { }) () , and `.call()`函数的括号包装 - (function() { }) () 和 `.call()`
【发布时间】:2014-02-19 13:47:43
【问题描述】:

我写 javascript 已经有一段时间了,最​​近一直在玩 coffeescript。我注意到coffeescript以以下方式编译函数:

(function() {

}).call()

我也注意到人们是这样写函数的:

(function() {

})()

据我了解,这些是自称的匿名函数。首先,.call()() 之间的区别是 .call() 只是 () 的一种更语义化的写法。

另外,当通常不需要时,为什么coffeescript 将整个文件包装在一个匿名函数中?这有什么性能或其他优势吗?什么时候应该使用这种自调用匿名函数?

谢谢

【问题讨论】:

标签: javascript coffeescript


【解决方案1】:

使用 .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();
        }
    }

})();

当我们不希望我们的用户也可以公开访问这些方法时,我们会这样做。

【讨论】:

    猜你喜欢
    • 2015-10-09
    • 2015-05-03
    • 2012-07-20
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多