“var FOO = FOO ||{}“(为该变量分配一个变量或一个空对象)在 Javascript 中是什么意思?

What does "var FOO = FOO || {}" (assign a variable or an empty object to that variable) mean in Javascript?

提问人:Ricardo Sanchez 提问时间:6/22/2011 最后编辑:JJJRicardo Sanchez 更新时间:10/26/2021 访问量:22305

问:

查看在线源代码,我在几个源文件的顶部遇到了它。

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

但我不知道有什么作用。|| {}

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

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

JavaScript 命名空间 variable-declaration or-operator

评论

0赞 Robert Harvey 6/23/2011
注意:对问题进行了编辑,以反映这是 Javascript 源文件顶部常见的 Code Pattern。

答:

3赞 sudipto 6/22/2011 #1

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

1赞 pimvdb 6/22/2011 #2

运算符采用两个值:||

a || b

如果 a 为真,它将返回 。否则,它将返回 .ab

假值为 、 、 、 和 。真实的价值观是其他一切。nullundefined0""NaNfalse

因此,如果尚未设置(是)它将返回。aundefinedb

评论

0赞 Orbling 6/22/2011
我不确定假是否应该作为实际的词语永久存在。有趣,但并不完全标准。:-)
4赞 Alnitak 6/22/2011
@Orbling它们通常用于在 JS 中谈论这些值。
0赞 Tim Büthe 6/22/2011
+1 用于正确描述运算符,因为它不是逻辑运算符。有时它被称为“默认运算符”。
0赞 Alnitak 6/22/2011
@Tim JS(和 Perl)与 C、C++ 和 Java 版本之间的唯一区别是 JS 不会将结果转换为布尔值。它仍然是一个逻辑运算符。||
0赞 Orbling 6/22/2011
@Alnitak:可能是因为过去JS开发者的非专业背景。
25赞 Spudley 6/22/2011 #3
var AEROTWIST = AEROTWIST || {};

基本上,这一行是说将变量设置为变量的值,或将其设置为空对象。AEROTWISTAEROTWIST

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

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

这基本上和说的一样:

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

希望能有所帮助。

评论

1赞 Alnitak 6/22/2011
实际上,在上一个示例中,范围会很好,因为JS没有块范围
0赞 Spudley 6/22/2011
@Alnitak - 嗯,你是对的;我最近一直在处理闭包,我忘记了基础知识。我会编辑答案。
155赞 Alnitak 6/22/2011 #4

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

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

之所以使用它,是因为如果您有两个(或更多)文件:

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

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

两者共享相同的命名空间,然后无论两个文件的加载顺序如何,您仍然可以在对象中正确获取并正确定义。func1func2MY_NAMESPACE

加载的第一个文件将创建初始对象,任何后续加载的文件都将扩充该对象。MY_NAMESPACE

有用的是,这还允许异步加载共享相同命名空间的脚本,这可以缩短页面加载时间。如果标签设置了属性,则无法知道它们将按何种顺序进行解释,因此如上所述,这也解决了该问题。<script>defer

评论

3赞 Ricardo Sanchez 6/22/2011
正是这种情况,开头有几个声明完全相同的 js 文件,非常感谢!
43赞 Spudley 6/22/2011
+1 用于阅读字里行间并解释这样做的原因。当有人给出用户真正想要的答案而不仅仅是他要求的答案时,这总是好的。:)
1赞 Darren Kopp 6/23/2011
我喜欢说这是 JavaScript :)#ifndef/#define
2赞 crazy2be 6/23/2011
||当您想要提供可选参数并将它们初始化为默认值(如果未提供)时,也非常有用:function foo(arg1, optarg1, optarg2) { optarg1 = optarg1 || 'default value 1'; optarg2 = optart2 || 'defalt value 2';}
1赞 Alnitak 6/26/2011
@crazy2be如果默认值为真,则不起作用,但假值也是合法的,因为运算符无法从 .||undefinedfalsey
7赞 alessioalex 11/19/2011 #5

||是为未定义的函数参数设置默认值:

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') {
  // ...
}

评论

0赞 Fabrício Matté 4/6/2013
你不需要在前面,将函数的执行上下文作为形式参数输入,因此它已经声明了。varaa
-1赞 ZER0 3/14/2012 #6

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

var AEROTWIST;
AEROTWIST = AEROTWIST || {};
11赞 Benny Code 8/21/2015 #7

主要包括两个部分。var FOO = FOO || {};

#1 防止覆盖

想象一下,您的代码被拆分为多个文件,而您的同事也在处理一个名为 的对象。然后,它可能导致有人已经定义并为其分配了功能(例如函数)的情况。然后,如果您不检查它是否已经存在,您将覆盖它。FOOFOOskateboard

问题案例:

// 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!');
};

在这种情况下,如果您在 HTML 中加载 JavaScript 文件,该函数将消失,因为 Homer 定义了一个新对象(因此覆盖了 Bart 的现有对象),因此它只知道该函数。skateboardhomer.jsbart.jsFOOdonut

因此,您需要使用 which 表示“FOO 将被分配给 FOO(如果它已经存在)或一个新的空白对象(如果 FOO 不存在)。var 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!');
};

由于 Bart 和 Homer 现在在定义其方法之前检查是否存在 of,因此您可以按任何顺序加载,而无需覆盖彼此的方法(如果它们具有不同的名称)。所以你总是会得到一个对象,它有方法和(耶!FOObart.jshomer.jsFOOskateboarddonut

#2 定义一个新对象

如果您已经通读了第一个示例,那么您现在已经知道 .|| {}

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

var FOO = {};

FOO.skateboard = function() {
  alert('I like skateboarding!');
};
0赞 bob 10/26/2021 #8

对于 || 操作,JS 将返回它找到的第一个“真实”值(从左到右读取):

var bob = false || undefined ||  0  ||  null || "hi"
//          ^          ^         ^      ^        ^
//          nope       nope      nope   nope     yip
//
// => bob = "hi"

// --------------
// breaking
// --------------
var bob = false || "hi" ||  0  ||  null || undefined
//          ^       ^
//          nope    yip <-- stops here
//                          the rest are ignored
//
// => bob = "hi"

另一个技巧是在访问之前使用 && (and) 来确保某些东西存在。

对于&&操作,JS将返回它找到的LAST“truthy”值(从左到右读取)。

例如,如果尝试从多级对象中读取属性。

var obj = {
        foo : {
            bar : "hi"
        }
    }

var bob = obj && obj.foo && obj.foo.bar;
//          ^        ^              ^
//          yip      yip            use this
//
// => bob = "hi"

// --------------
// breaking:
// --------------
var bob = obj && obj.foo && obj.foo.sally && obj.foo.bar;
//        ^          ^              ^
//        yip        yip            nope  <-- stops here, 
//                   ^                        and returns the last "yip"
//                   |                        the rest are ignored   |
//                   '-----------------------------------------------'
//
// => bob = obj.foo

两者 ||&& 操作从左到右读取...因此,您可以拥有通常可能会向右侧抛出错误的东西,因为一旦 JS 检测到真值/假值,它就会停止从左到右读取。