什么是「;x=x |{}”;JavaScript中的技术-它如何影响这种生活?

什么是「;x=x |{}”;JavaScript中的技术-它如何影响这种生活?,javascript,syntax,iife,Javascript,Syntax,Iife,首先,一个伪代码示例: ;(function(foo){ foo.init = function(baz) { ... } foo.other = function() { ... } return foo; }(window.FOO = window.FOO || {})); 这样称呼: FOO.init(); 我的问题: 什么是:window.FOO=window.FOO | |{}的技术名称/说明 我理解代码的作用。。。请参阅下文,了解我的提问原因

首先,一个伪代码示例:

;(function(foo){

    foo.init = function(baz) { ... }

    foo.other = function() { ... }

    return foo;

}(window.FOO = window.FOO || {}));
这样称呼:

FOO.init();
我的问题:
  • 什么是:
    window.FOO=window.FOO | |{}
    的技术名称/说明
我理解代码的作用。。。请参阅下文,了解我的提问原因


提出问题的理由: 我这样称呼传入的全局:

;(function(foo){
    ... foo vs. FOO, anyone else potentially confused? ...
}(window.FOO = window.FOO || {}));
。。。但是我只是不喜欢用小写的“
foo
”,因为全局被称为大写的
foo
。。。这似乎令人困惑

如果我知道这种技术的技术名称,我可以说:

;(function(technicalname){
    ... do something with technicalname, not to be confused with FOO ...
}(window.FOO = window.FOO || {}));
我看到了一个最近的(很棒的)例子,他们称之为“
exports
”:

我想我只是想标准化我的编码惯例。。。我想知道职业选手做什么,他们怎么想(这就是为什么我在这里问的)

图案 您描述的模式没有正式名称,因为它是三个单独的模式的组合。每个模式都有多个名称,但在本文中,我将使用以下术语:

  • 关闭
  • 别名
  • 命名空间扩展
关闭 整个模式的基础是
闭包
。它只是一个函数,用于限定变量和函数的范围,以使它们不会污染全局命名空间:

不结案 闭包,在本例中为 将变量保留在闭包中的优点是,您不必担心有人会覆盖您正在使用的变量。对于经常使用的临时变量,如
i
j
,这一点尤为重要

别名 此模式的第二个重要部分是别名。别名允许在闭包中定义和使用变量,而无需担心它所在的全局命名空间

无别名 带别名 这一点尤其重要,因为这意味着可以通过在单个位置更改名称来跨大型JavaScript文件更改全局名称空间。这是件好事™. 此外,缩小器可以将内部别名缩短为单个字母的变量名,如
a
,从而在缩小时节省大量字节

命名空间扩展 命名空间扩展模式依赖于or运算符的合并行为(
| |
)。在许多语言中,
&
|
返回
true
false
,但在JavaScript中,
&
返回第一个
false
值(
false
0
null
未定义的
),和
|
返回第一个
truthy
值(任何不是
错误的值)。对于这两个运算符,如果未找到相应的类型,则返回最后一个参数。这使得
|
操作符成为定义新名称空间的一种方便方法,仅当它不存在时

没有命名空间扩展 使用命名空间扩展 这很有用,因为它允许使用其他属性和方法扩展命名空间,而不必担心属性和方法的定义顺序

在第一个示例中,
FileA
需要在
FileB
之前执行:

FileA.js FileB.js 在第二个示例中,
File1
File2
可以按任意顺序执行:

File1.js File2.js 现在一起 将每个模式一起使用可创建一个非常强大的模块化脚本:

//use foo internally so that you don't have to worry about
//what the global namespace is called
(function (foo) {
    //declare variables internally that you want to keep local to the script
    var i,
        len,
        internal,
        qux;
    //declare functions/properties on the alias when you want to expose them
    foo.bar = function () {...};
//extend the global namespace so that existing extensions are persistent
}(window.FOO = window.FOO || {}));

我一直把它理解为

至于影响你的生活,如果它已经被实例化,你将传入
window.FOO
,如果它没有实例化,则传入一个空对象

您也可以将其理解为:

window.FOO = window.FOO || {};
;(function(foo){

    foo.init = function(baz) { ... }

    foo.other = function() { ... }

    return foo;

}(window.FOO));
就我个人而言,我更喜欢不同的模式:

var FOO;
if (!FOO) {
    FOO = {};
}
(function () {
    "use strict";
    FOO.prop1 = 'bar';
    FOO.bar = function (z) {
        return z + 1;
    };
}());

我发现它不那么令人困惑,并帮助我确保干净的名称空间。

为了补充pete的答案,另一种形式是:

;(function() {
  var Foo = window.Foo = window.Foo || {};

  Foo.foo  = 'bar';
  Foo.baz  = function() {
    return "Hello World!";
  };
})();

我通常使用local
var
来给minifier节省几个字节的机会。当您在命名空间的多个层次上工作时,这会产生更大的影响,例如
var MyView=window.MyApp.Views.MyView

正如其他人所指出的,您的第一个问题完全独立于第二个问题。它们之间没有任何关系,只是您决定将它们合并到一个语句中,而不是两个语句中

对于第一个问题,Douglas Crockford将其称为默认赋值。如中所示,如果变量存在,则不使用它,否则将其初始化为指定的默认值。当您看到类似以下内容的内容时:

foo = foo || {};
你的思维应该是这样的:

foo defaults to `{}`
从技术上讲,它实际上是“如果foo是falsy,那么将
{}
赋值给foo”,但是我们假设任何falsy,比如零、null或未定义的值,在我们使用它时,都是对
foo
无效的值。此外,单词
default
已经暗示“如果未定义foo”


但是,说到这里,知道了你的第二个问题,很明显,default作为传递给你的iLife的参数的名称并不是一个合适的词。该参数所做的只是将方法和属性附加到传入的对象。在这种情况下,导出是合适的,如“这些是对象的公开导出成员”。我认为,attach也是一个合适的名称,如“将这些东西附加到对象”。我个人的偏好是简单地将它命名为object,这是您希望传入的类型。

您可以调用参数
FOO
。这将隐藏
window.FOO
,除非您使用
window.FOO
显式引用它。它们是相同的对象。请随意给同一个名字或不同的名字<代码>警报(window.FOO==FOO);
if (typeof window.Foo === 'undefined') {
    window.foo = {};
}
window.foo = window.foo || {};
window.foo = {};
window.foo.bar = 'baz';
window.foo.fizz = 'buzz';
window.foo = window.foo || {};
window.foo.bar = 'baz';
window.foo = window.foo || {};
window.foo.fizz = 'buzz';
//use foo internally so that you don't have to worry about
//what the global namespace is called
(function (foo) {
    //declare variables internally that you want to keep local to the script
    var i,
        len,
        internal,
        qux;
    //declare functions/properties on the alias when you want to expose them
    foo.bar = function () {...};
//extend the global namespace so that existing extensions are persistent
}(window.FOO = window.FOO || {}));
window.FOO = window.FOO || {};
;(function(foo){

    foo.init = function(baz) { ... }

    foo.other = function() { ... }

    return foo;

}(window.FOO));
var FOO;
if (!FOO) {
    FOO = {};
}
(function () {
    "use strict";
    FOO.prop1 = 'bar';
    FOO.bar = function (z) {
        return z + 1;
    };
}());
;(function() {
  var Foo = window.Foo = window.Foo || {};

  Foo.foo  = 'bar';
  Foo.baz  = function() {
    return "Hello World!";
  };
})();
foo = foo || {};
foo defaults to `{}`