JavaScript匿名构造函数:!函数(){}();

JavaScript匿名构造函数:!函数(){}();,javascript,function,constructor,Javascript,Function,Constructor,我见过在JavaScript中创建匿名构造函数的语法: var Application = Application || {}; !function(window, Application) { Application.property = {/*...*/} Application.method = function(){/*...*/} }(window, Application); 我想了解以下几部分: 使用第一行(即varo=o | |{};)与只声明varo=(funct

我见过在JavaScript中创建匿名构造函数的语法:

var Application = Application || {};
!function(window, Application) {
   Application.property = {/*...*/}
   Application.method = function(){/*...*/}
}(window, Application);
我想了解以下几部分:

  • 使用第一行(即
    varo=o | |{};
    )与只声明
    varo=(function(){})()相比有什么好处
  • 为什么
    是否用于函数前面
  • 当它们是全局对象时,为什么要将
    窗口
    应用程序
    作为参数传递
  • 这是匿名构造函数最方便的方法吗?这比:
  • (4a)

    或4b)


    我不知道所有的答案,但我会尽力回答

  • 使用var Application=Application | |{};简单地说就是你在处理范围。如果已经定义了“Application”变量,那么它只意味着它继承了当前作用域,并且现在在当前作用域中可用。如果不是,则“| |”部分(表示或)表示将创建为空对象。您要处理的是创建一个对象,然后对其执行操作,而不仅仅是将结果原封不动地返回。这就是为什么不应该使用“o=(function(){…});”。“o”将是函数的结果,而不是对象

  • 使用“!function”会将其视为一个表达式,但这可能很棘手,因为您可能需要从相反的角度思考。例如!null表示您正在检查它是否为null,而不是检查它是否为null

  • 再次传入窗口和应用程序对象处理作用域。它显式地将它们传递到函数中,然后在最后返回它们。把这想象成把衣服放进洗衣机。你把它们放进去,事情就会发生,然后你把它们拿出来。这是一个非常粗糙的想法,不是最好的例子,但这是我不久前的想法。你们把衣服放进去,然后调用漂洗功能,然后调用肥皂功能,然后再次漂洗,然后旋转排水

  • 希望其他人能回答这个问题,我不确定有什么不同


  • 第一行是确保
    应用程序
    始终存在,通常用于预期
    应用程序
    应该已经存在的情况,并且该函数只是扩展现有对象。如果它不存在,这可以确保访问未定义属性时不会出现错误。您的示例仅在
    应用程序
    尚不存在的情况下等效。在所有其他情况下,您的代码将删除现有的
    应用程序
    ,这几乎肯定不是您的意图

    Vatev的评论解释了
    可以。这是另一种语法,用于使所讨论的函数成为自动执行的匿名函数。(顺便说一句,它还接受函数的返回值-当前未定义的
    ,并翻转其真实性,因此其计算结果为true。但由于结果未存储在任何变量中,这显然不是目的。)


    最后,为什么要将
    窗口
    应用程序
    传递到函数中并在那里使用它?这是一项安全功能,以防以后其他代码更改
    窗口
    应用程序
    。它保证在匿名函数中,
    窗口
    应用程序
    正是您所期望的。在您给出的速记示例中,这似乎无关紧要——毕竟,如果您立即使用这些变量而不存储它们,为什么要保护它们?在许多情况下,您从这个函数返回一些内容,然后
    窗口
    应用程序
    将存储在闭包中,因此您将保留变量。它可以避免人们后来决定说
    Application={…}

    ,因为迄今为止有两个答案忽略了这两个细节:jQuery之类的库使用的模式使用以下两个参数:

    (function (window, undefined) {
        window.myPlugin = ...;
    })(window);
    
    这里有两件事:

    • 未定义
      被指定为参数,但未传入。这样,
      undefined
      保证在内部范围内具有预期值。这仅适用于允许覆盖未定义的
      的旧浏览器(尽管这样做一直被认为是不好的做法——这正是像jQuery这样的库所做的,以避免其他代码干扰它们的代码)

    • 在范围内对全局对象(如
      窗口
      )进行别名处理,可以进一步缩小代码(也适用于
      未定义的
      )。显然,对别名对象的引用越多,保存的内容就越多:

    相比

    (function(){window.myPlugin=...;window.somethingElse=...;if(whatever===undefined){return;}})();
    

    使用
    window
    不会节省太多,因为通常情况下,您都不想将全局对象弄得乱七八糟。但是别名
    未定义
    可以为您节省大量空间。

    它并不比您的替代代码好。我会说更糟。这很有趣,但为什么呢?这两个片段并不相同<代码>!使用function(){}()
    代替
    (function(){})(
    ,请参阅以了解详细信息。1。其优点是,如果应用程序实例已经存在,则不会使用新实例对其进行重写。也做了很多工作,因为它对这些对象使用别名,这将允许缩短这些对象,从而在缩小时节省更多的位和字节。“安全原因”不是一个很大的原因:如果该值被覆盖,它将被覆盖–期间。您可以保护自己的唯一值是
    undefined
    ,方法是将其指定为参数,但不传入任何内容(仅适用于允许覆盖
    undefined
    )的旧浏览器)。除此之外,别名全局对象对于缩小非常有用。@IngoBürk如果您将
    应用程序
    传入函数并将其存储在闭包中,在闭包之外,说
    Application=“hello”(function (window, undefined) {
        window.myPlugin = ...;
    })(window);
    
    (function(w,u){w.myPlugin=...;w.somethingElse=...;if(whatever===u){return;}})(window);
    
    (function(){window.myPlugin=...;window.somethingElse=...;if(whatever===undefined){return;}})();