JavaScript中的"x = x || {}"技术是什么 - 它如何影响这个IIFE?

mhu*_*lse 3 javascript syntax iife

首先,一个伪代码示例:

;(function(foo){

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

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

    return foo;

}(window.FOO = window.FOO || {}));
Run Code Online (Sandbox Code Playgroud)

这样称呼:

FOO.init();
Run Code Online (Sandbox Code Playgroud)

我的问题:

  • 什么是技术名称/描述:window.FOO = window.FOO || {}

我理解代码的作用...请参阅下面的我的原因.


询问理由:

我这样称呼全球传递:

;(function(foo){
    ... foo vs. FOO, anyone else potentially confused? ...
}(window.FOO = window.FOO || {}));
Run Code Online (Sandbox Code Playgroud)

...但我只是不喜欢称小写" foo",考虑到全局被称为大写FOO......它只是看起来令人困惑.

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

;(function(technicalname){
    ... do something with technicalname, not to be confused with FOO ...
}(window.FOO = window.FOO || {}));
Run Code Online (Sandbox Code Playgroud)

我见过一个最近(很棒)的例子,他们称之为" exports":

;(function(exports){
    ...
}(window.Lib = window.Lib || {}));
Run Code Online (Sandbox Code Playgroud)

我想我只是想把我的编码惯例标准化......我想了解专业人士做了什么以及他们如何思考(这就是我在这里问的原因)!

zzz*_*Bov 5

图案

(function (foo) {
    ...code...
    foo.bar = baz;
    ...more code...
}(window.FOO = window.FOO || {});
Run Code Online (Sandbox Code Playgroud)

您描述的模式没有正式名称,因为它是三个单独的模式组合在一起.每个模式都有多个名称,但对于这篇文章,我将使用以下术语:

  • 关闭
  • 别号
  • 名称扩展名

关闭

整个模式的基础是closure.它只是一个用于扩展变量和函数的函数,以便它们不会污染全局命名空间:

没有关闭
//these declare window.foo and window.bar respectively
//as such, they pollute the global namespace
var foo;
function bar() {}
Run Code Online (Sandbox Code Playgroud) 在这种情况下,关闭立即调用的功能表达式(IIFE)
(function () {
    //these declare foo and bar within the function
    //but they are not accessible outside the function
    var foo;
    function bar() {}
}());
Run Code Online (Sandbox Code Playgroud)

将变量保存在闭包中的优点是,您不必担心有人会覆盖您正在使用的变量.这对于诸如ij经常使用的临时变量尤其重要.

别号

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

没有别名
(function () {
    ...
    foo = window.SomeFunction(bar, baz);
    ...
}());
Run Code Online (Sandbox Code Playgroud) 使用别名
(function (sf) { //local name
    ...
    foo = sf(bar, baz);
    ...
}(window.SomeFunction)); //global namespace
Run Code Online (Sandbox Code Playgroud)

这一点尤为重要,因为这意味着可以通过在单个位置更改名称来跨大型JavaScript文件更改全局命名空间.这是A Good Thing™.此外,minifiers可以将内部别名缩短为单个字母变量名称,例如a,在缩小时节省大量字节.

命名空间扩展

命名空间扩展模式依赖于or运算符(||)的合并行为.在许多语言中,&&||在回报truefalse,但在JavaScript中,&&返回第一个falsey值(false,0,'',null,undefined),并||返回第一个truthy值(任何非falsey).对于两个运算符,如果未找到相应的类型,则返回最后一个参数.这使得||操作符只有在尚未存在的情况下才能定义新命名空间.

无命名空间扩展
if (typeof window.Foo === 'undefined') {
    window.foo = {};
}
Run Code Online (Sandbox Code Playgroud) 使用命名空间扩展
window.foo = window.foo || {};
Run Code Online (Sandbox Code Playgroud)

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

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

FileA.js
window.foo = {};
window.foo.bar = 'baz';
Run Code Online (Sandbox Code Playgroud) FileB.js
window.foo.fizz = 'buzz';
Run Code Online (Sandbox Code Playgroud)

在该第二示例,File1并且File2可以以任何顺序被执行:

File1.js
window.foo = window.foo || {};
window.foo.bar = 'baz';
Run Code Online (Sandbox Code Playgroud) File2.js
window.foo = window.foo || {};
window.foo.fizz = 'buzz';
Run Code Online (Sandbox Code Playgroud)

现在都在一起了

使用每个模式一起创建一个非常强大的模块化脚本

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