Javascript CoffeeScript模块的模式
在查看时,我注意到大多数(如果不是全部的话)模块的定义如下:Javascript CoffeeScript模块的模式,javascript,node.js,coffeescript,Javascript,Node.js,Coffeescript,在查看时,我注意到大多数(如果不是全部的话)模块的定义如下: (function() { ... }).call(this); 此模式看起来像是将整个模块包装在一个匿名函数中并调用自身 这种方法的优点(和缺点)是什么?有没有其他方法可以实现同样的目标 这种方法的优点是它创建了私有变量,因此不会与变量名发生冲突: (function() { var privateVar = 'test'; alert(privateVar); // test })(); alert(typeo
(function() {
...
}).call(this);
此模式看起来像是将整个模块包装在一个匿名函数中并调用自身
这种方法的优点(和缺点)是什么?有没有其他方法可以实现同样的目标 这种方法的优点是它创建了私有变量,因此不会与变量名发生冲突:
(function() {
var privateVar = 'test';
alert(privateVar); // test
})();
alert(typeof privateVar); // undefined
添加.call(this)
使this
关键字引用的值与函数外部引用的值相同。如果未添加,则此
关键字将自动引用全局对象
下面是一个显示差异的小示例:
function coffee(){
this.val = 'test';
this.module = (function(){
return this.val;
}).call(this);
}
var instance = new coffee();
alert(instance.module); // test
function coffee(){
this.val = 'test';
this.module = (function(){
return this.val;
})();
}
var instance = new coffee();
alert(typeof instance.module); // undefined
这与以下语法类似:
(function() {
}());
它被称为即时函数。立即定义并执行该函数。这样做的好处是,您可以将所有代码放在这个块中,并将函数分配给单个全局变量,从而减少全局命名空间污染。它在函数中提供了一个很好的包含范围
这是我在编写模块时使用的典型模式:
var MY_MODULE = (function() {
//local variables
var variable1,
variable2,
_self = {},
etc
// public API
_self = {
someMethod: function () {
}
}
return _self;
}());
不确定缺点到底是什么,如果其他人知道,我很乐意了解它们。哈门的回答很好,但让我详细说明一下CoffeeScript编译器是在哪里完成的,以及为什么 当您使用
coffee-cfoo.coffee
编译某个东西时,您总会得到一个foo.js
如下所示:
(function() {
...
}).call(this);
为什么呢?好吧,假设你把一个任务
x = 'stringy string'
在foo.coffee
中。当它看到这一点时,编译器会问:x
是否已经存在于这个作用域中,还是外部作用域中?如果不是,它会在JavaScript输出的该范围的顶部放置一个var x
声明
现在假设你写信
x = 42
在bar.coffee
中,编译这两个文件,并将foo.js
与bar.js
连接以进行部署。你会得到
(function() {
var x;
x = 'stringy string';
...
}).call(this);
(function() {
var x;
x = 42;
...
}).call(this);
因此foo.coffee
中的x
和bar.coffee
中的x
是完全独立的。这是CoffeeScript的一个重要部分:变量永远不会从一个.coffee文件泄漏到另一个文件,除非显式导出(通过附加到共享全局文件,或附加到Node.js中的导出
)
您可以通过使用-b
(“裸”)标志来覆盖这一点,但这只能在非常特殊的情况下使用。如果您将它与上面的示例一起使用,您将得到以下输出
var x;
x = 'stringy string';
...
var x;
x = 42;
...
这可能会产生可怕的后果。要自己测试这一点,请尝试在foo.coffee
中添加setTimeout(->alert x),1
。请注意,如果您使用两个单独的
标记将两个JS文件包含在一个页面上,那么您不必自己连接这两个JS文件,它们仍然有效地作为一个文件运行
通过隔离不同模块的作用域,CoffeeScript编译器使您不用担心项目中的不同文件是否会使用相同的局部变量名。这是JavaScript世界中的常见做法(例如,请参阅,或任何jQuery插件)-CoffeeScript只为您处理它。请注意,您查看的是生成的JavaScript,而不是编写的CoffeeScript。我认为缺点是1)您必须更加努力地跨模块共享状态(至少在JavaScript中的CoffeeScript中,您可以省略
var
,但这通常是不被鼓励的,例如通过jsLint),并且2)额外的函数调用和字节会带来一点点开销。但是99%的时候,额外的安全是值得的。不,这不是一个相关的答案。他在问(function(){})。具体地调用(this),而不是你举例说明的(function(){})()。哈门的回答很中肯,回答得很好。谢谢你的帮助!你的答案写得很好,真的帮助我更好地理解咖啡脚本(和JavaScript)。。。谢谢到底是谁在玩这样的全局变量?我不想做任何没有课程或结束的事情。必须显式导出是令人讨厌的。我在开发angularjs时开始使用coffeescript。Andularjs的策略是杀死所有全局变量,所以在我的例子中,-b标记足够好:)