以下内容可能对自己编写代码没有太大用处,但压缩程序可以使用逗号操作符来缩小代码。例如:
if(x){foo();return bar()}else{return 1}
将成为:
return x?(foo(),bar()):1
现在可以使用三元运算符? :
,因为逗号运算符(在某种程度上)允许将两个语句写成一个语句。
这样做的好处在于它可以实现一些整洁的压缩(39->24字节)。
我想强调的是,在var a, b
中的逗号不是逗号运算符,因为它不存在于一个表达式中。在var
语句中,逗号具有特殊含义。a, b
在表达式中将引用这两个变量,并且求值为b
,而在var a, b
中不是这种情况。
if (条件) 变量1 = 值1, 变量2 = 值2;
我个人认为,在可能的情况下避免使用括号可以使代码更易读。 - Aidiakapi逗号运算符允许您在需要一个表达式的地方放置多个表达式。 由逗号分隔的多个表达式的结果值将是最后一个表达式的值。
我个人并不经常使用它,因为很少有情况需要多个表达式,并且没有比使用逗号运算符更清晰的编写代码的方法。一个有趣的可能性是在 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
}
在这里,您可以看到i ++,j ++
可以放置在允许一个表达式的位置。 在这种特殊情况下,多个表达式用于副作用,因此复合表达式采用最后一个表达式的值并不重要,但在其他情况下可能会更加重要。
const actions = _.chain(options)
.pairs() // 1
.filter(selectActions) // 2
.map(createActionPromise) // 3
.reduce((state, pair) => (state[pair[0]] = pair[1], state), {}) // 4
.value();
使用 pairs
把传递给该函数的所有选项拆分开,将{a: 1, b: 2}
变成[['a', 1], ['b', 2]]
此属性对数组被过滤为系统中被视为“操作”的属性。
然后,使用map
将数组中第二个索引替换为表示该操作的 Promise 的函数
最后,调用reduce
将每个 "property array" (['a', 1]
)合并回一个最终对象中。
最终结果是转换后的options
参数版本,其中只包含适当的键,其值可以被调用函数使用。
仅看
.reduce((state, pair) => (state[pair[0]] = pair[1], state), {})
你可以看到,reduce函数从一个空的状态对象state
开始,对于每对表示键和值的元素,该函数返回相同的state
对象,在将属性添加到与键/值对应的对象后。由于ECMAScript 2015的箭头函数语法,函数体是一个表达式,因此逗号运算符允许一个简洁且有用的"迭代器"函数。
就我个人而言,在使用ECMAScript 2015 +箭头函数以更功能化的方式编写JavaScript时,我遇到了许多案例。话虽如此,在遇到箭头函数之前(例如在编写问题时),我从未有意识地使用过逗号运算符。
.reduce((state, [key, value]) => (state[key] = value, state), {})
。我知道这样做有违回答本身的用意,但是.reduce((state, [key, value]) => Object.assign(state, { [key]: value }), {})
可以消除逗号运算符的需要。 - Patrick Roberts逗号运算符的另一个用途是在repl或控制台中隐藏不关心的结果,仅出于方便而这样做。
例如,如果您在repl或控制台中评估myVariable = aWholeLotOfText
,它将打印您刚刚分配的所有数据。 这可能是页数和页数,如果您不想看到它,您可以改为评估myVariable = aWholeLotOfText,'done'
,则 repl/console 将只打印'done'。
Oriel正确指出†,自定义的toString()
或get()
函数甚至可能使这个方法更有用。
逗号运算符不仅仅是JavaScript特有的,它在其他语言中也可用,例如C和C++。作为一个二元操作符,当第一个操作数通常是一个表达式时,它非常有用,因为第一个操作数具有第二个操作数所需的期望副作用。维基百科上的一个例子如下:
i = a += 2, a + b;
显然,你可以编写两行不同的代码,但使用逗号是另一种选项,有时更易读。
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
查找第一个父元素,类似于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">
while ((el = el.parentNode) && (el.tagName != tagName.toUpperCase()))
在上下文中完全可以。 - PitaJconst stopPropagation = event => (event.stopPropagation(), event);
const preventDefault = event => (event.preventDefault(), event);
const both = compose(stopPropagation, preventDefault);
您可以将逗号替换为||或&&,但是您需要知道函数返回值。
更重要的是,逗号分隔符传达了意图 - 代码不关心左操作数的求值结果,而其他选择可能有其存在的原因。这反过来使得代码更易于理解和重构。如果函数返回类型发生更改,则上面的代码不会受到影响。
当然,您可以以其他方式实现相同的效果,但不如逗号运算符简洁。如果||和&&在常用情况下被使用,那么逗号运算符也可以。
tap
函数(https://ramdajs.com/docs/#tap)所做的事情。本质上,您执行了一个副作用,然后返回初始值;在函数式编程中非常有用 :) - avalanche1除此之外,我还没有发现它的实际用途,但是这里有一个场景,James Padolsey 很好地运用了这个技巧来检测IE在while循环中:
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]
在JavaScript中有一种“奇怪”的方法,可以通过使用逗号运算符间接调用函数。
这里有一个详细的描述: 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);
}());
您可以访问全局变量,因为eval
在直接调用和间接调用时的工作方式不同。
我今天刚看到这个,看了一下管道操作符的提议和部分应用程序......
let $; // Hack-style topic variable
let result = (
$= books,
$= filter($, _ => _.title = "..."),
$= map($, _ => _.author),
$);
$=
之间的空格可以模拟正确的管道符号 |>
的感觉。请注意,“主题”变量 $
可以是任何内容,它只是缩写,表示反复覆盖变量。因此,更像是...// blocking inside an IIFE
let result = (() => {
let $;
$ = books;
$ = filter($, _ => _.title = "..."),
$ = map($, _ => _.author),
return $;
})()
let result = books
|> filter($, _ => _.title = "..."
|> map($, _ => _.author)
const double = (x) => 2 * x;
const add = (x, y) => x + y;
const boundScore = (min, max, score) => Math.max(min, Math.min(max, score));
const calculateScore = ($) => (
$= double($),
$= add($, 20),
$= boundScore(0, 100, $),
(console.log($), $)
)
const score = calculateScore(28)
return
或单个 $
,默认情况下将返回最后分配的值。 - icetbr
var i, j, k;
和var i; var j, var k
有什么区别? - Salman A,
运算符有任何关系。那行代码在C#中也是有效的,但是在C#中不存在,
运算符。 - gdoron,
)不总是逗号操作符,而且它从不是逗号操作符。因此,即使没有逗号操作符,C#仍然可以自由地使用逗号作为语法的一部分。请注意,这里不需要写解释。 - Seth Carnegiea
和b
的值,你可以这样写:a = [b][b = a,0]
。这会把当前的b
放到数组中。第二个“[]”是属性访问符号。被访问的索引是0
,但是在将a
分配给b
之前,这不会发生,因为现在b
被保留在数组中。逗号运算符让我们在“[]”中执行多个表达式。 - user1106925