逗号运算符何时有用?

gdo*_*ica 74 javascript comma-operator

我在examples()和关于它的MDN文档中读到了关于"逗号运算符"的这个问题,但我想不出它有用的场景.,

那么,逗号运算符何时有用?

pim*_*vdb 113

以下内容可能不是很有用,因为您不自己编写,但是minifier可以使用逗号运算符缩小代码.例如:

if(x){foo();return bar()}else{return 1}
Run Code Online (Sandbox Code Playgroud)

会成为:

return x?(foo(),bar()):1
Run Code Online (Sandbox Code Playgroud)

? :操作者现在可以使用,因为逗号运算符(在一定程度上)允许两个语句被写为一个语句.

有用的,因为它允许一些整齐压缩(39 - > 24个字节在这里).


我想强调的是,在逗号var a, b不是逗号运算符,因为它没有一个中存在的表达.逗号在var 语句中具有特殊含义.a, b在表达式中将引用两个变量并进行求值b,而不是这种情况var a, b.

  • 前几天我只是搞乱[Closure Compiler](http://closure-compiler.appspot.com/home),看看它究竟做了什么,我确实注意到了这个替代. (15认同)
  • 你是怎么想的?你有没有看过哪里?它真的被使用了吗? (3认同)
  • 我认为在您的代码中有用的类似用法是在内联if语句中分配多个变量。例如:`if(condition)var1 = val1,var2 = val2;`我个人认为尽可能避免使用方括号会使代码更具可读性。 (2认同)
  • 大约只有在将日志语句添加到表达式中时才使用逗号运算符(foo =>(console.log('foo',foo),foo)),或者如果我对reduce迭代器变得太聪明了。(pairs.reduce((acc,[k,v])=>(acc [k] = v,acc),{})) (2认同)

jfr*_*d00 33

逗号运算符允许您将多个表达式放在需要一个表达式的位置. 由逗号分隔的多个表达式的结果值将是最后一个逗号分隔表达式的值.

我并不经常使用它,因为没有那么多的情况下需要多个表达式,并且编写代码的方式不会比使用逗号运算符更容易混淆.一个有趣的可能性是在for循环结束时,您希望递增多个变量:

// j is initialized to some other value
// as the for loop executes both i and j are incremented
// because the comma operator allows two statements to be put in place of one
for (var i = 0; i < items.len; i++, j++) {
    // loop code here that operates on items[i] 
    // and sometimes uses j to access a different array
}
Run Code Online (Sandbox Code Playgroud)

在这里,您可以看到i++, j++可以放在允许一个表达式的位置.在这种特殊情况下,多个表达式用于副作用,因此复合表达式采用最后一个的值并不重要,但在其他情况下,这可能实际上很重要.


Syy*_*nth 31

在Javascript中编写功能代码时,逗号运算符通常很有用.

考虑一下我为SPA写的这段代码,其中包含以下内容

const actions = _.chain(options)
                 .pairs() // 1
                 .filter(selectActions) // 2
                 .map(createActionPromise) // 3
                 .reduce((state, pair) => (state[pair[0]] = pair[1], state), {}) // 4
                 .value();
Run Code Online (Sandbox Code Playgroud)

这是一个相当复杂但真实的场景.当我解释发生了什么时,请耐心等待,并在此过程中为逗号操作员提供案例.


这使用了Underscore的链接

  1. 拆开所有的传递给这个函数的选项使用pairs ,这将转{ a: 1, b: 2}[['a', 1], ['b', 2]]

  2. 这些属性对数组被过滤,被认为是系统中的"动作".

  3. 然后数组中的第二个索引替换为一个函数,该函数返回表示该操作的promise(使用map)

  4. 最后,调用reduce将每个"属性数组"(['a', 1])合并回最终对象.

最终结果是options参数的转换版本,它只包含适当的键,其值可由调用函数使用.


只是看着

.reduce((state, pair) => (state[pair[0]] = pair[1], state), {})
Run Code Online (Sandbox Code Playgroud)

您可以看到reduce函数以空状态对象开始state,并且对于表示键和值的每对,该函数state在向对应于键/值对的对象添加属性后返回相同的对象.由于ECMAScript 2015的箭头函数语法,函数体是一个表达式,因此,逗号运算符允许简洁实用的"iteratee"函数.

我个人在使用ECMAScript 2015 + Arrow Functions以更实用的方式编写Javascript时遇到了很多案例.话虽如此,在遇到箭头函数之前(例如在编写问题时),我从未以任何刻意的方式使用逗号运算符.

  • 很好的答案,但如果我可以建议一些更易读的东西:`.reduce((state, [key, value]) =&gt; (state[key] = value, state), {})`。我意识到这违背了答案的目的,但是 `.reduce((state, [key, value]) =&gt; Object.assign(state, { [key]: value }), {})` 将消除对完全是逗号运算符。 (5认同)
  • 这是关于程序员如何/何时使用逗号运算符的唯一真正有用的答案。非常有用,尤其是在“reduce”中 (3认同)
  • 虽然现在 Object.assign 可能更惯用,甚至只是扩展运算符,但我不确定它们当时是否得到广泛使用。我还要指出,虽然逗号运算符有点晦涩,但在数据集非常大的情况下,这可以产生更少的垃圾。不过,解构肯定会提高可读性! (2认同)

Jul*_*hal 17

逗号运算符的另一个用途是隐藏在repl或控制台中不关心的结果,纯粹是为了方便.

例如,如果您myVariable = aWholeLotOfText在repl或控制台中进行评估,它将打印您刚刚分配的所有数据.这可能是页面和页面,如果您不想看到它,您可以改为评估myVariable = aWholeLotOfText, 'done',并且repl/console将只打印'done'.

Oriel正确地指出定制toString()get()功能甚至可能使这个有用.

  • 哈,非常好的主意!(最后一个答案实际上回答了这个问题,与几乎所有答案不同{以及 3 个删除的答案,你需要 20K 声誉才能看到......}) (2认同)

tas*_*oor 12

逗号运算符不是特定于JavaScript的,它可以用于其他语言,如C和C++.作为二元运算符,当第一个操作数(通常是表达式)具有第二个操作数所需的副作用时,这很有用.来自维基百科的一个例子:

i = a += 2, a + b;
Run Code Online (Sandbox Code Playgroud)

显然,您可以编写两行不同的代码,但使用逗号是另一种选择,有时更具可读性.

  • 感谢您的投入,所以我猜**真实和良好的**使用`,`是罕见的... (5认同)
  • 这看起来令人困惑……wtf。 (3认同)

sha*_*sir 6

我不同意Flanagan,并说,逗号非常有用,并且允许编写更易读和优雅的代码,特别是当你知道你在做什么时:

这是关于逗号用法的详细文章:

来自那里的几个例子用于证明示范:

function renderCurve() {
  for(var a = 1, b = 10; a*b; a++, b--) {
    console.log(new Array(a*b).join('*'));
  }
}
Run Code Online (Sandbox Code Playgroud)

斐波那契发生器:

for (
    var i=2, r=[0,1];
    i<15;
    r.push(r[i-1] + r[i-2]), i++
); 
// 0,1,1,2,3,5,8,13,21,34,55,89,144,233,377
Run Code Online (Sandbox Code Playgroud)

找到第一个父元素,jQuery .parent()函数的模拟:

function firstAncestor(el, tagName) {
    while(el = el.parentNode, el && (el.tagName != tagName.toUpperCase()));
    return el;
}

//element in http://ecma262-5.com/ELS5_HTML.htm
var a = $('Section_15.1.1.2'); 

firstAncestor(a, 'div'); //<div class="page">
Run Code Online (Sandbox Code Playgroud)

  • 我不确定我是否会说任何一个**更具可读性**但它确实非常漂亮所以+1 (5认同)
  • 在最后一个示例中,while 循环中不需要逗号,`while ((el = el.parentNode) &amp;&amp; (el.tagName != tagName.toUpperCase()))` 在这种情况下就可以了。 (2认同)

Jer*_*her 6

在 JavaScript 中可以通过使用逗号运算符间接调用函数来完成一些“奇怪”的事情。

这里有很长的描述: Indirect function call in JavaScript

通过使用此语法:

(function() {
    "use strict";
  
    var global = (function () { return this || (1,eval)("this"); })();
    console.log('Global === window should be true: ', global === window);
  
    var not_global = (function () { return this })();
    console.log('not_global === window should be false: ', not_global === window);
  
  }());
Run Code Online (Sandbox Code Playgroud)

您可以访问全局变量,因为eval直接调用与间接调用时的工作方式不同。


Sar*_*raz 5

除此之外,我还没有发现它的实际用途,但是在以下情况下,James Padolsey在while循环中很好地使用了该技术来进行IE检测

var ie = (function(){

    var undef,
        v = 3,
        div = document.createElement('div'),
        all = div.getElementsByTagName('i');

    while ( // <-- notice no while body here
        div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
        all[0]
    );

    return v > 4 ? v : undef;

}());
Run Code Online (Sandbox Code Playgroud)

必须执行这两行:

div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
all[0]
Run Code Online (Sandbox Code Playgroud)

在逗号运算符内部,虽然可以使它们以某种方式成为单独的语句,但两者都被评估。

  • 这可能是一个`do`-`while`循环。 (3认同)

Lam*_*kis 5

我发现逗号运算符在编写这样的助手时最有用。

const stopPropagation = event => (event.stopPropagation(), event);
const preventDefault = event => (event.preventDefault(), event);
const both = compose(stopPropagation, preventDefault);
Run Code Online (Sandbox Code Playgroud)

您可以用 || 替换逗号 或&&,但是你需要知道函数返回什么。

比这更重要的是,逗号分隔符传达了意图——代码不关心左操作数的计算结果,而替代品可能有另一个存在的原因。这反过来又使理解和重构变得更容易。如果函数返回类型发生变化,上面的代码不会受到影响。

当然,您可以通过其他方式实现相同的目标,但没有那么简洁。如果|| 和 && 找到了一个常用的地方,逗号运算符也是如此。

  • 类似于 Ramda\Lodash 对 `tap` 所做的事情 (https://ramdajs.com/docs/#tap)。本质上,你正在执行一个副作用,然后返回初始值;在函数式编程中非常有用:) (2认同)