55

以下只是一个理论上的 JavaScript 问题。我很好奇以下是否可以转换为单个语句:

if(!window.foo){
  window.foo = [];
}
window.foo.push('bar');

这段代码大家可能以前都写过,但是一行行能搞定吗?
起初我认为这样的事情会起作用:

(window.foo || window.foo = []).push('bar');

但由于分配无效,这不起作用。接下来我尝试在推送上链接一些东西,但这不起作用,因为推送不返回数组。

关于这是否可以用纯 JavaScript 完成的任何想法?
(顺便说一下,结果应该是这样window.foo = ['bar']

4

4 回答 4

92

你的任务倒退了*。它应该是:

(window.foo = window.foo || []).push('bar');

||JavaScript中的运算符不返回布尔值。如果左侧为真,则返回左侧,否则返回右侧。

a = a || [];

相当于

a = a ? a : [];

所以写上面的另一种方法是:

(window.foo = window.foo ? window.foo : []).push('bar');

* 详情见评论

于 2013-01-30T21:30:22.877 回答
15

如果您添加括号,您的代码就可以正常工作,以便它符合您的预期:

(window.foo || (window.foo = [])).push('bar');

没有括号,它认为它应该window.foo || window.foo首先评估,然后将数组分配给结果,这是不可能的。

于 2013-01-30T21:36:34.160 回答
13

这个问题让我玩了不同的选择来娱乐。返回长度而不是原始数组引用太糟糕push了,但是对于更短的表达式,拥有可以立即迭代、映射等的东西会很有帮助。

window.foo = (window.foo||[]).concat(['bar']); // always returns array, allowing:
(window.foo = (window.foo||[]).concat(['bar'])).forEach( ... )

(window.foo = window.foo||[]).push('bar'); // always returns length

window.foo && window.foo.push('bar') || (window.foo = ['bar']); // playing around
于 2013-01-30T21:30:29.570 回答
4

2021 更新

@zzzzBov 的有用答案

(window.foo = window.foo || []).push('bar');

可以使用新||=运算符进一步简化逻辑 OR 赋值1

(window.foo ||= []).push('bar');

1参见tcs39/proposal-logical-assignment,目前处于4 阶段,主要浏览器支持

于 2021-11-08T14:44:08.573 回答