什么是"x = x ||"{}";JavaScript中的技巧-以及如何影响此IIFE? [英] What is the "x = x || {}" technique in JavaScript - and how does it affect this IIFE?
问题描述
首先,是一个伪代码示例:
First, a pseudo code example:
;(function(foo){
foo.init = function(baz) { ... }
foo.other = function() { ... }
return foo;
}(window.FOO = window.FOO || {}));
这样称呼:
FOO.init();
我的问题:
-
window.FOO = window.FOO ||的技术名称/描述是什么?{}
?
我了解代码的作用...出于我的询问原因,请参见下文.
I understand what the code does... See below for my reason(s) for asking.
我这样称呼传入的全局对象:
I'm calling the passed in global like so:
;(function(foo){
... foo vs. FOO, anyone else potentially confused? ...
}(window.FOO = window.FOO || {}));
...但是我只是不喜欢称呼小写的" foo
",考虑到全局被称为大写的 FOO
...这似乎令人困惑.
... but I just don't like calling that lowercase "foo
", considering that the global is called capitalized FOO
... It just seems confusing.
如果我知道这项技术的技术名称,我可以说:
If I knew the technical name of this technique, I could say:
;(function(technicalname){
... do something with technicalname, not to be confused with FOO ...
}(window.FOO = window.FOO || {}));
我看到了一个最近的(很棒的)例子,他们称其为" exports
":
I've seen a recent (awesome) example where they called it "exports
":
;(function(exports){
...
}(window.Lib = window.Lib || {}));
我想我只是想标准化我的编码约定...我想学习专业人员的做法以及他们的想法(这就是为什么我在这里问这个问题!)!
I guess I'm just trying to standardize my coding conventions... I'd like to learn what the pros do and how they think (that's why I'm asking here)!
推荐答案
模式
(function (foo) {
...code...
foo.bar = baz;
...more code...
}(window.FOO = window.FOO || {});
您描述的模式没有正式名称,因为它是三个单独的模式组合而成.每个模式都有多个名称,但是在这篇文章中,我将使用以下术语:
There is no formal name for the pattern you describe, because it's three separate patterns combined. Each pattern goes by multiple names, but for this post I will use the following terminology:
- 关闭
- 别名
- 命名空间扩展名
整个模式的基础是 closure
.它只是一个用于定义变量和函数范围的函数,这样它们就不会污染全局名称空间:
The base of the entire pattern is the closure
. It is simply a function that is used to scope variables and functions such that they don't pollute the global namespace:
//these declare window.foo and window.bar respectively
//as such, they pollute the global namespace
var foo;
function bar() {}
在这种情况下,请关闭立即调用的功能表达式(IIFE)
(function () {
//these declare foo and bar within the function
//but they are not accessible outside the function
var foo;
function bar() {}
}());
将变量保留在闭包中的优点是,您不必担心有人会覆盖正在使用的变量.这对于经常使用的临时变量(例如 i
或 j
)尤其重要.
The advantage of keeping variables within a closure is that you won't have to worry about someone overwriting the variables that you're using. This is especially important for temporary variables such as i
or j
that are used often.
此模式的第二个重要部分是别名.别名允许在闭包中定义和使用变量,而无需担心变量位于哪个全局命名空间中.
The second important part of this pattern is aliasing. Aliasing allows a variable to be defined and used within a closure without needing to worry about what global namespace it resides in.
(function () {
...
foo = window.SomeFunction(bar, baz);
...
}());
使用别名
(function (sf) { //local name
...
foo = sf(bar, baz);
...
}(window.SomeFunction)); //global namespace
这一点特别重要,因为这意味着可以通过在单个位置更改名称来更改大型JavaScript文件中的全局名称空间.这是一件好事.此外,缩小器可以将内部别名缩短为单个字母变量名称,例如 a
,从而在缩小时节省大量字节.
This is especially important as it means that the global namespace can be changed across a large JavaScript file by changing the name in a single location. This is A Good Thing™. Additionally, minifiers can shorten the internal alias to a single letter variable name such as a
, making for significant byte savings on minification.
名称空间扩展模式取决于or运算符( ||
)的合并行为.在许多语言中,&&
和 ||
返回 true
或 false
,但是在JavaScript中,&
返回第一个 falsey
值( false
, 0
,''
, null
, undefined
)和 ||
返回第一个 truthy
值(不是 falsey的任何值
).对于这两个运算符,如果找不到相应的类型,则返回最后一个参数.这使得 |||
运算符成为仅当新名称空间不存在时定义新名称的便捷方法.
The namespace extension pattern relies on the coalescing behavior of the or operator (||
). In many languages, &&
and ||
return either true
or false
, but in JavaScript, &&
returns the first falsey
value (false
, 0
, ''
, null
, undefined
), and ||
returns the first truthy
value (anything that's not falsey
). For both operators, if the respective type is not found, the last argument is returned. This makes the ||
operator a convenient way of defining a new namespace only if it doesn't already exist.
if (typeof window.Foo === 'undefined') {
window.foo = {};
}
具有名称空间扩展名
window.foo = window.foo || {};
这很有用,因为它允许使用其他属性和方法扩展名称空间,而不必担心定义属性和方法的顺序.
This is useful because it allows a namespace to be extended with additional properties and methods without having to worry about which order the properties and methods were defined in.
在第一个示例中,需要在 FileB
之前执行 FileA
:
In this first example, FileA
would need to be executed before FileB
:
window.foo = {};
window.foo.bar = 'baz';
FileB.js
window.foo.fizz = 'buzz';
在第二个示例中,可以按任意顺序执行 File1
和 File2
:
In this second example, File1
and File2
could be executed in any order:
window.foo = window.foo || {};
window.foo.bar = 'baz';
File2.js
window.foo = window.foo || {};
window.foo.fizz = 'buzz';
现在在一起
将每个模式一起使用会创建一个非常强大的模块化脚本:
All together now
Using each pattern together creates a very powerful modular script:
//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 || {}));
这篇关于什么是"x = x ||"{}";JavaScript中的技巧-以及如何影响此IIFE?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!