题 什么是“var FOO = FOO ||在Javascript中{}“(将变量或空对象赋给该变量)是什么意思?


看一下在线源代码,我在几个源文件的顶部看到了这个。

var FOO = FOO || {};
FOO.Bar = …;

但我不知道是什么 || {} 确实。

我知道 {} 等于 new Object() 而且我认为 || 是为了“如果它已经存在使用它的值,否则使用新对象。

为什么我会在源文件的顶部看到这个?


89
2018-06-22 12:10


起源


注意:编辑该问题是为了反映这是Javascript源文件顶部常见的代码模式。 - Robert Harvey♦


答案:


你猜测的意图 || {} 非常接近。

在文件顶部看到的这种特殊模式用于创建 命名空间,即一个命名对象,在该对象下可以创建函数和变量而不会过度污染全局对象。

原因 为什么 如果您有两个(或更多)文件,它的使用是这样的:

var MY_NAMESPACE = MY_NAMESPACE || {};
MY_NAMESPACE.func1 = {
}

var MY_NAMESPACE = MY_NAMESPACE || {};
MY_NAMESPACE.func2 = {
}

这两个文件共享相同的命名空间,然后加载两个文件的顺序无关紧要,你仍然可以得到 func1 和 func2 在...中正确定义 MY_NAMESPACE 对象正确。

加载的第一个文件将 创建 最初的 MY_NAMESPACE 对象,以及任何后续加载的文件 增加 物体。

有用的,这也允许 异步 加载共享相同命名空间的脚本,这可以改善页面加载时间。如果 <script> 标签有 defer 属性集你不知道它们将被解释的顺序,所以如上所述,这也解决了这个问题。


142
2018-06-22 12:15



这是完全一样的,有一些js文件在开始时具有完全相同的声明,非常感谢! - Ricardo Sanchez
在行间读取+1并解释这样做的原因。当有人给出用户实际的答案时总是好的 通缉 而不仅仅是他要求的那个。 :) - Spudley
我想说这是javascript的#ifndef / #define :) - Darren Kopp
|| 当你想提供可选参数并将它们初始化为默认值(如果没有提供)时,它也非常有用: function foo(arg1, optarg1, optarg2) { optarg1 = optarg1 || 'default value 1'; optarg2 = optart2 || 'defalt value 2';} - crazy2be
@ crazy2be如果默认值是真的不起作用,但假的值也是合法的,因为 || 操作员无法分辨 undefined 从 falsey。 - Alnitak


var AEROTWIST = AEROTWIST || {};

基本上这条线就是设定了 AEROTWIST 变量到的值 AEROTWIST 变量,或将其设置为空对象。

双管 || 是OR语句,OR的第二部分仅在第一部分返回false时执行。

因此,如果 AEROTWIST 已经有一个值,它将保留为该值,但如果之前未设置,则将其设置为空对象。

它与说这个基本相同:

if(!AEROTWIST) {var AEROTWIST={};}

希望有所帮助。


20
2018-06-22 12:15



实际上,你的上一个例子中的范围会很好,因为 JS没有块范围 - Alnitak
@Alnitak - 嗯,你是对的;我最近一直在处理关闭过多的问题,而且我已经忘记了基础知识。我会编辑答案。 - Spudley


||的另一个常见用途是也为未定义的函数参数设置默认值:

function display(a) {
  a = a || 'default'; // here we set the default value of a to be 'default'
  console.log(a);
}

// we call display without providing a parameter
display(); // this will log 'default'
display('test'); // this will log 'test' to the console

其他编程中的等价物通常是:

function display(a = 'default') {
  // ...
}

5
2017-11-18 16:57



你不需要 var 在前面 a, a 输入函数的执行上下文作为 形式参数因此它已经宣布。 - Fabrício Matté
是的,更新了答案 - alessioalex


主要有两个部分 var FOO = FOO || {}; 盖子。

#1防止覆盖

想象一下,您的代码分为多个文件,您的同事也在处理一个名为的Object FOO。然后它可能导致某人已经定义的情况 FOO 并为其分配功能(如a skateboard 功能)。如果你没有检查它是否已经存在,那么你会覆盖它。

有问题的案例:

// Definition of co-worker "Bart" in "bart.js"
var FOO = {};

FOO.skateboard = function() {
  alert('I like skateboarding!');
};

// Definition of co-worker "Homer" in "homer.js"
var FOO = {};

FOO.donut = function() {
  alert('I like donuts!');
};

在这种情况下 skateboard 如果加载JavaScript文件,函数将会消失 homer.js 后 bart.js 在你的HTML中,因为荷马定义了一个新的 FOO 对象(从而覆盖Bart的现有对象)所以它只知道 donut 功能。

所以你需要使用 var FOO = FOO || {}; 这意味着“FOO将被分配给FOO(如果它已存在)或新的空白对象(如果FOO已经不存在)。

解:

var FOO = FOO || {};

// Definition of co-worker Bart in bart.js
FOO.skateboard = function() {
  alert('I like skateboarding!');
};

// Definition of co-worker Homer in homer.js
var FOO = FOO || {};

FOO.donut = function() {
  alert('I like donuts!');
};

因为巴特和荷马正在检查是否存在 FOO 在他们定义他们的方法之前,你可以加载 bart.js 和 homer.js 以任何顺序,而不是重写彼此的方法(如果他们有不同的名称)。所以你总会得到一个 FOO 具有方法的对象 skateboard 和 donut (好极了!)。

#2定义一个新对象

如果你已经阅读了第一个例子,那么你现在已经知道了它的目的是什么 || {}

因为如果没有 FOO 对象然后OR-case将变为活动状态并创建一个新对象,因此您可以为其分配函数。喜欢:

var FOO = {};

FOO.skateboard = function() {
  alert('I like skateboarding!');
};

4
2017-08-21 15:14





如果AEROTWIST中没有值或者它为null或未定义,则分配给新AEROTWIST的值将为{}(空白对象)


3
2018-06-22 12:13





|| 运算符有两个值:

a || b

如果是的话 truthy,它会回来 a。否则,它将返回 b

虚假的价值观是 nullundefined0""NaN 和 false。真实的价值观是其他一切。

因此,如果 a 没有设定(是吗? undefined)它会回来 b


1
2018-06-22 12:15



我不确定 truthy 和 falsey 应该作为实际的词语延续下去。有趣,但不完全标准。 :-) - Orbling
@Orbling他们很常用于在JS中讨论这些值。 - Alnitak
+1用于正确描述运算符,因为它不是逻辑运算符。有时它被称为“默认运营商”。 - Tim Büthe
@Tim唯一的区别 || 在JS(和Per​​l)中,C,C ++和Java中的版本是JS不会将结果转换为布尔值。它仍然是一个合乎逻辑的运营商。 - Alnitak
@Alnitak:可能是由于过去JS开发人员的非专业背景。 - Orbling


请注意,在某些版本的IE中,此代码将无法按预期工作。因为 var,变量被重新定义  如此分配 - 如果我没记错的话 - 你最终会得到一个新的对象。这应该解决问题:

var AEROTWIST;
AEROTWIST = AEROTWIST || {};

-1
2018-03-14 12:21