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

参见英文答案 > What does “var FOO = FOO || {}” (assign a variable or an empty object to that variable) mean in Javascript?                                    7个
首先,一个伪代码示例:

;(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 || {}));

我见过一个最近(很棒)的例子,他们称之为“出口”:

;(function(exports){
    ...
}(window.Lib = window.Lib || {}));

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

解决方法:

图案

(function (foo) {
    ...code...
    foo.bar = baz;
    ...more code...
}(window.FOO = window.FOO || {});

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

>关闭
>别名
>命名空间扩展

关闭

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

没有关闭

//these declare window.foo and window.bar respectively
//as such, they pollute the global namespace
var foo;
function bar() {}

关闭,在这种情况下,Immediately Invoked Functional Expression (IIFE)

(function () {
    //these declare foo and bar within the function
    //but they are not accessible outside the function
    var foo;
    function bar() {}
}());

将变量保存在闭包中的优点是,您不必担心有人会覆盖您正在使用的变量.这对于经常使用的临时变量(例如i或j)尤为重要.

别号

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

没有别名

(function () {
    ...
    foo = window.SomeFunction(bar, baz);
    ...
}());

使用别名

(function (sf) { //local name
    ...
    foo = sf(bar, baz);
    ...
}(window.SomeFunction)); //global namespace

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

命名空间扩展

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

无命名空间扩展

if (typeof window.Foo === 'undefined') {
    window.foo = {};
}

使用命名空间扩展

window.foo = window.foo || {};

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

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

FileA.js

window.foo = {};
window.foo.bar = 'baz';

FileB.js

window.foo.fizz = 'buzz';

在第二个示例中,File1和File2可以按任何顺序执行:

File1.js

window.foo = window.foo || {};
window.foo.bar = 'baz';

File2.js

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 || {}));
上一篇:Javascript闭包和IIFE(立即调用函数表达式)


下一篇:JavaScript IIFE