What advantages does using (function(window, document, undefined) { … })(window, document) confer?
我想使用这种模式是一种新的热点,但我不理解它的优势是什么,也不理解范围界定的含义。
模式:
1 2 3 4 5 6 | (function(window, document, undefined){ window.MyObject = { methodA: function() { ... }, methodB: function() { ... } }; })(window, document) |
所以我有几个问题。
封装这样的对象有什么特别的优势吗?为什么输入窗口和文档而不是正常访问?为什么要把
我已经习惯了我称之为Javascript封装的Crockford风格(因为我从Douglas Crockford Javascript视频中获得了它)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | NameSpace.MyObject = function() { // Private methods // These methods are available in the closure // but are not exposed outside the object we'll be returning. var methodA = function() { ... }; // Public methods // We return an object that uses our private functions, // but only exposes the interface we want to be available. return { methodB: function() { var a = methodA(); }, methodC: function() { ... } } // Note that we're executing the function here. }(); |
这些模式中的一个在功能上比另一个好吗?第一个是另一个的进化吗?
Why are window and document being fed in instead of just being accessed normally?
一般来说,为了加快标识符解析过程,将它们作为局部变量可以有所帮助(尽管IMO的性能改进可以忽略不计)。
传递全局对象也是非浏览器环境中广泛使用的一种技术,在该环境中,全局范围内没有
1 2 3 4 | (function (global) { //.. })(this); // this on the global execution context is // the global object itself |
Why the heck is undefined being passed in?
之所以这样做,是因为ecmascript 3中的
1 2 3 4 | undefined = true; // mutable (function (undefined) { alert(typeof undefined); //"undefined", the local identifier })(); // <-- no value passed, undefined by default |
如果仔细观察
javascript中的
只是为了记录,在EcmaScript 5中,此属性被设置为不可写…
Is attaching the object we're creating directly to window a particularly good idea?
当您在另一个函数范围内时,这是一种常用的声明全局属性的方法。
这种风格确实比"Crockford"风格带来了一些好处。首先,传递
此外,您还可以获得执行速度方面的好处。当我第一次读到@joekarl关于它提供性能优势的断言时,我想,"这似乎有点假。"所以我用一个测试页来描述实际的性能。引用
当然,在实践中,您永远不会引用
Why the heck is
undefined being passed in?
因为(如@cms所提到的)令牌
Is attaching the object we're creating directly to window a particularly good idea?
我认为这主要是针对需要在多个窗口上下文中运行的代码。假设您有一个复杂的应用程序,其中包含许多iframe和/或子窗口。它们都需要在myObject中运行代码,但您只需要加载一次。因此,您可以将其加载到您选择的任何窗口/帧中,但可以为每个窗口/帧创建一个myObject,其中包含对适当窗口和文档的引用。
采用未定义的参数试图防止未定义的参数可以更改:
1 2 | undefined = 3; alert(undefined); |
参见CMS关于如何提高安全性的答案。
我同意你使用克罗克福德的风格。
回答你的问题
1.封装这样的对象有什么特别的优势吗?
我能看到的唯一优势是,通过创建窗口和文档局部变量而不是全局变量,您可以通过不能直接覆盖其中一个变量来获得一些额外的安全性,并且通过它们都是局部变量来获得一些性能增益。
2.为什么窗口和文档被输入而不是被正常访问?
上述地址。局部变量往往更快,但随着JIT编译的这些天,这已成为名义。
3.为什么未定义的heck被传入?
没有线索…
4.将我们直接创建的对象附加到窗口是否是一个特别好的主意?
可能不会,但我仍然坚持Crockford的模式,因为将函数附加到Window对象会通过Window对象将其暴露到全局堆栈的其余部分,而不是通过非标准命名空间将其暴露。