逗号运算符何时有用?

我在expression式( , )和MDN文档中阅读了关于“逗号运算符”的这个问题,但我想不出有用的场景。

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

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

 if(x){foo();return bar()}else{return 1} 

会成为:

 return x?(foo(),bar()):1 

这个? : ? :运算符现在可以使用,因为逗号运算符(在某种程度上)允许将两个语句写成一个语句。

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


我想强调的一点是, var a, b中的逗号不是逗号运算符,因为它不存在于expression式中 。 逗号在var 语句中有特殊的含义。 a, b中的expression式将引用这两个variables并评估为b ,而var a, b则不是这种情况。

逗号运算符允许您在需要一个expression式的地方放置多个expression式。 用逗号分隔的多个expression式的结果值将是最后一个用逗号分隔的expression式的值。

我不经常亲自使用它,因为没有那么多的情况下,期望多于一个的expression式,并且编写代码的方式比使用逗号操作符的方式更less。 一个有趣的可能性是在for循环结束时,当你想要增加一个以上的variables时:

 // 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 } 

在这里你可以看到i++, j++可以放在允许一个expression式的地方。 在这种特殊情况下,多个expression式用于副作用,因此复合expression式具有最后一个的值并不重要,但是在其他情况下,这可能是非常重要的。

在JavaScript中编写function代码时,逗号运算符通常很有用。

考虑一下我为SPA写的这段代码,后面有如下的代码

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

这是一个相当复杂的,但现实世界的情况。 在我解释发生了什么事情的时候,忍受着我,并且在这个过程中为逗号运算符做了个案。


这使用了Underscore的链接

  1. { a: 1, b: 2}变成[['a', 1], ['b', 2]]

  2. 这个属性对的数组被过滤,哪些被认为是系统中的“动作”。

  3. 然后数组中的第二个索引被一个函数replace,该函数返回一个表示该动作的promise(使用map

  4. 最后,调用reduce会将每个“属性数组”( ['a', 1] )合并到最终的对象中。

最终结果是options参数的转换版本,其中只包含适当的键,其值可由调用函数消耗。


只看着

 .reduce((state, pair) => (state[pair[0]] = pair[1], state), {}) 

您可以看到reduce函数以空状态对象state ,并且对于表示键和值的每个对来说,该函数在向对应于键/值对的对象添加属性之后返回相同的state对象。 由于ECMAScript 2015的箭头函数语法,函数体是一个expression式,因此逗号运算符允许一个简洁而有用的“迭代”函数。

就我个人而言,在使用ECMAScript 2015 +箭头函数编写更具function的Javascript风格的同时,遇到了许多案例。 话虽如此,在遇到箭头function之前(例如在写问题的时候),我从来没有用过任何故意的方式使用逗号操作符。

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

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

Oriel正确地指出定制的toString()get()函数甚至可能使这个有用。

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

 i = a += 2, a + b; 

显然你可以写两行不同的代码,但使用逗号是另一种select,有时更易读。

除此之外,我还没有发现它的实际用途,但这里是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; }()); 

这两行必须执行:

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

而在逗号运算符内部,两者都被评估,尽pipe人们可能会以某种方式将它们分开。

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

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

来自这里的几个例子来certificate示范:

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

斐波纳契发电机:

 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 

find第一个父元素,类似于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"> 

我最终使用它的一个典型情况是在可选参数parsing期间。 我认为这使得它更具可读性和更简洁,使得参数parsing不占主导地位。

 /** * @param {string} [str] * @param {object} [obj] * @param {Date} [date] */ function f(str, obj, date) { // handle optional arguments if (typeof str !== "string") date = obj, obj = str, str = "default"; if (obj instanceof Date) date = obj, obj = {}; if (!(date instanceof Date)) date = new Date(); // ... } 

在JavaScript中可以通过使用逗号运算符间接调用一个函数来实现某些“奇怪”的function。

这里有一个很长的描述: 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); }()); 

可以使用逗号运算符的另一个领域是代码混淆

比方说一个开发者写这样的代码:

 var foo = 'bar'; 

现在,她决定混淆代码。 使用的工具可能会改变这样的代码:

 var Z0b=(45,87)>(195,3)?'bar':(54,65)>(1,0)?'':'baz';// Z0b == 'bar' 

演示: http : //jsfiddle.net/uvDuE/