使用(函数(窗口,文档,未定义){...})(窗口,文档)赋予什么优势?

Gre*_*ell 59 javascript

我想使用这种模式是新的热点,但我不明白它的优点是什么,我不理解范围的含义.

模式:

(function(window, document, undefined){
  window.MyObject = {
    methodA: function() { ... },
    methodB: function() { ... }
  };
})(window, document)
Run Code Online (Sandbox Code Playgroud)

所以我对此有几个问题.

封装像这样的对象有什么特别的优势吗?
为什么窗口文档被输入而不是正常访问?
为什么undefined要传递这个?
将我们正在创建的对象直接附加到窗口是一个特别好的主意吗?

我已经习惯了我称之为Crockford风格的Javascript封装(因为我把它从Douglas Crockford Javascript视频中删除了).

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.
}();
Run Code Online (Sandbox Code Playgroud)

其中一种模式在功能上优于另一种吗?第一个是另一个的演变吗?

CMS*_*CMS 50

为什么窗口和文档被输入而不是正常访问?

通常,为了加强标识符解析过程,将它们作为局部变量可以提供帮助(尽管IMO的性能改进可以忽略不计).

传递全局对象也是非浏览器环境中广泛使用的技术,您window在全局范围内没有标识符,例如:

(function (global) {
  //..
})(this); // this on the global execution context is 
          // the global object itself
Run Code Online (Sandbox Code Playgroud)

为什么heck未定义被传入?

之所以这样做是因为undefinedECMAScript 3中的全局属性是可变的,这意味着某人可以更改其影响代码的值,例如:

undefined = true; // mutable
(function (undefined) {
  alert(typeof undefined); // "undefined", the local identifier
})(); // <-- no value passed, undefined by default
Run Code Online (Sandbox Code Playgroud)

如果仔细观察undefined实际上没有传递(函数调用没有参数),这是获取undefined值的可靠方法之一,而不使用该属性window.undefined.

这个名字undefined在JavaScript并不代表什么特别的,是不是关键字一样true,false等...,它只是一个标识符.

仅仅为了记录,在ECMAScript 5中,这个属性是不可写的......

将我们正在创建的对象直接附加到窗口是一个特别好的主意吗?

当您在另一个函数范围内时,这是用于声明全局属性的常用方法.

  • @ShaunLuttin它只是使参考更快.不仅如此,你可以按照大多数人习惯的方式使用它.您通常不会将它用作:window.document.whatever(),您可以将其用作:document.whatever().如果你不这样做而且你做了"document.whatever()",实际上,你使用的是全局窗口对象而不是范围对象,即使它不够清晰.不可否认,它可以实现更好的最小化.窗口可以变为"w"并且文档"d".只是因为它可以减少大量字符的脚本. (2认同)

jos*_*736 26

这种特殊风格确实带来了"Crockford"风格的一些优点.主要是,传递windowdocument允许脚本更有效地缩小.minifier可以将这些参数重命名为单字符名称,每个引用分别保存5和7个字节.这可以加起来:jQuery引用window33次和document91次.将每个标记缩小为一个字符可以节省802个字节.

此外,您可以获得执行速度优势.当我第一次阅读@joekarl关于它提供性能优势的断言时,我想,"这看起来相当虚假." 所以我用测试页面描述了实际的性能.引用window 一亿次,本地变量引用在Firefox 3.6中提供适度的20%速度增加(4200 ms到3400ms),在Chrome 9中增加了31,000%(13秒到400ms).

当然,window在实践中你永远不会参考100,000,000次,甚至10,000个直接参考只需要1ms的Chrome,所以这里的实际性能增益几乎可以忽略不计.

为什么undefined要传递这个?

因为(如@CMS所述)令牌undefined实际上是未定义的.null与之不同,它没有特殊含义,您可以像任何其他变量名一样自由地分配给此标识符.(但请注意,在ECMAScript 5中不再适用.)

将我们正在创建的对象直接附加到窗口是一个特别好的主意吗?

window对象是全局范围,因此无论您是否明确地编写"窗口",这正是您在某些时候所做的事情. window.Namespace = {};并且Namespace = {};是等价的.

  • +1为缩小优势 (3认同)