在CoffeeScript中?= vs || =

时间:2013-03-07 02:02:28

标签: javascript coffeescript operators

我正在尝试选择一个可靠的运算符,“如果未定义或初始化变量,则声明并初始化”。

考虑一个例子(语义并不重要):

window.test ?= 123

location.origin ||= location.protocol + "//" + location.host

这会被翻译成以下Javascript:

var _ref;

if ((_ref = window.test) == null) {
  window.test = 123;
}

location.origin || (location.origin = location.protocol + "//" + location.host);

哪种方式更好?在我看来,||=运算符更可靠,因为它也说明了“未定义”但是为什么CoffeeScript会推广使用?=呢?我错过了什么吗?

2 个答案:

答案 0 :(得分:7)

在JavaScript中,undefined == null 1 ,因此它确实考虑了undefined||=通常是不受欢迎的,因为它会覆盖任何虚假值,即使它不是nullundefined,例如,零或假。

1 在JavaScript中,==有时会隐式强制执行值,其中一个案例是nullundefined。 (见section 11.9.3 in the specification的第2和第3项)。

答案 1 :(得分:0)

  

我正在尝试选择一个可靠的运算符,“如果未定义或初始化变量,则声明并初始化”。

无法在符合ECMA-262的主机中有条件地声明变量。可以测试全局变量的存在,因为它们是全局(窗口)对象的属性(但它不会告诉您它们是否被创建为全局变量或属性)。测试全局:

// In global scope:
var global = this;

// Wherever:
if (global.hasOwnProperty('foo')) { // throws an error in IE
  // foo is a property of the global object
} 

无法测试局部变量(例如在函数内),因为您无法访问变量对象或执行上下文对象来测试它,您所能做的就是针对undefined进行测试或使用{ {1}}(丑陋的)。但需要这样做是非常糟糕的设计。

如果打算有条件地创建全局对象的属性,那么上面的内容将导致:

try..catch

但是,如果您还想测试属性是否已分配值,则:

if (!global.hasOwnProperty('foo')) { // throws an error in IE
  global.foo = 'whatever';
}

似乎更合适,好像上面的内容返回true,然后它既没有声明,也没有赋值,或者被赋值为if (typeof global.foo == 'undefined') { // works everywhere 。在所有情况下,您可能希望现在分配一个值。

undefined进行测试似乎不合理,因为它具有该值的唯一方法是显式分配(这意味着该属性存在且已被赋值)。