2011-09-01 108 views
4

一般认为,应该将Javascript代码包装在一个函数中以防止泄漏到全局范围,并将每个函数之外所需的任何内容分配给head对象(网页浏览器中的window)。Javascript包装方法之间的区别

我看到的这两种主要方法在野外:

方法1:

(function() { 
    // code here 
}).call(this); 

方法2:1

(function() { 
    // code here 
})(); 

方法是来自已编译的CoffeeScript代码和方法2似乎是jQuery插件的首选风格:

改进方法2的jQuery:

(function($) { 
    // JQuery Code 
})(jQuery); 

问题:之间有什么方法1方法2区别? CoffeeScript喜欢关注简洁,所以我认为CoffeeScript背后的人一定会选择方法2而不是方法1

回答

4

他们是非常不同的。

方法1使用call,允许你改变什么this是函数内部。例如:

(function() { 
    alert(this); // DOMWindow 
}).call(window); 


var myObj = {a: 0}; 
(function() { 
    alert(this); // Object => myObj {a: 0} 
}).call(myObj); 

不过要小心,你仍然可以转储的东西在全球范围内有两种方法:

(function() { 
    a = 5; // global 
    var p = 10; // private to this function 
})(); 
+0

问题询问有关呼叫(此),它与呼叫(窗口)不同。请参阅CoffeeScript示例,您将看不到呼叫(窗口) – liammclennan

+0

第一个是将函数内的* this *设置为与函数外部的* this *相同,可能它是全局对象(通常是*窗口*在浏览器中,但脚本可能被编写为支持非浏览器环境)。 – RobG

0

大多数时候是没有区别的。方法1显式设置'this'的值将在立即执行的函数中。

2

方法之一,两者之间的区别取决于上下文它们在使用。

如在方法中的一个,执行功能与call将使用第一参数作为“这个”内的 功能。在方法二中,函数中的'this'将引用全局对象,因为'this'没有被调用设置(除了在ES 5严格模式下,它将被定义)。

有了这些知识,试着想想如果这两个函数都是要加载到浏览器中的JS文件的根目录中的位置,会发生什么情况。

在这种情况下,在方法一中传递给'call'的'this'将引用窗口对象,它是浏览器中的全局对象。方法二将完成同样的事情,因为'this'未被调用设置的函数将其这个设置为全局对象(除了如上所述的ES5严格模式外)。

因此,对于这种情况,他们会表现相同。

但是,有些情况并非如此。

var obj = { 
    f: function() { 
    (function() { 
     // 'this' here is 'obj' if called as obj.f() 
    }).call(this); 

    (function() { 
     // 'this' not set by the call, defaults to 'window' (ES5 caveat) 
    })(); 
    } 
}; 

obj.f(); 

方法一更清晰,因为它显式地传递外部'this'的值,减少了混淆的机会,并增加了灵活性。

如果“这个”无关紧要,方法二更短更容易。

jQuery版本用作总是能够通过'$'变量访问jQuery的简单方法,同时仍允许jQuery之外的代码具有$意味着别的东西。