?= vs ||= in CoffeeScript

?= vs ||= in CoffeeScript

本文关键字:in CoffeeScript vs      更新时间:2023-09-26

我试图为"如果变量未定义或初始化,则声明和初始化"选择一个可靠的操作符。

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

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提倡使用?=代替?我错过什么了吗?

在JavaScript中,undefined == null 1,所以它确实占undefined||=通常是不可取的,因为它会覆盖任何假值,即使它不是nullundefined,例如,0或false。

1在JavaScript中,==有时隐式强制值,其中一种情况是nullundefined。(见规范第11.9.3节第2和3项)

我试图为"如果变量未定义或初始化,则声明并初始化"选择一个可靠的操作符。

不可能在符合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或使用try..catch(丑陋)进行测试。但是这样做是非常糟糕的设计。

如果目的是有条件地创建全局对象的属性,那么上面的结果是:

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

但是,如果您还想测试该属性是否已被赋值,则:

if (typeof global.foo == 'undefined') { // works everywhere

似乎更合适,如果上面返回true,那么它没有被声明,没有被赋值,或者被赋值为undefined。在所有情况下,您都可能想要赋值。

针对null进行测试似乎是不明智的,因为它具有该值的唯一方法是显式地赋值(这意味着该属性存在并且已被赋值)。