逗号运算符何时有用?
我在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的链接
-
把
{ a: 1, b: 2}
变成[['a', 1], ['b', 2]]
-
这个属性对的数组被过滤,哪些被认为是系统中的“动作”。
-
然后数组中的第二个索引被一个函数replace,该函数返回一个表示该动作的promise(使用
map
) -
最后,调用
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/