让我们从一个有趣的微博开始吧。

末尾的c是优先级最低的逗号操作符。逗号操作符是操作符优先级的最后一行,并且很少有文章记录,它隐藏着它的锋芒。它可能不是JavaScript强势操作符,但是我喜欢它。它简单、优雅并且你应该让它成为你的朋友。所以,我们开始吧--你需要更多了解JavaScript这个害羞英雄。

它是做什么的?

逗号操作符评估它的操作数(从左到右)并返回第二个操作数的值。(MDC

var a = (7, 5);
a; // var x, y, z;
x = (y=1, z=4);
x; //
y; //
z; //

你为什么把这些变量放在括号里?

因为运算符的优先级。一个JavaScript语句可以保护多个不同的运算符,下面语句包含三个运算符(*,+和,);

return 5 * 2 + 3, 22;

在一个语句中运算符优先级决定了运算符执行的顺序。运算符优先顺序的完整列表在这里。逗号运算符是所有运算符优先级最低的操作符。让我们模拟上面的例子怎么运行的:

// 原始的
return 5 * 2 + 3, 22;
// 运行*操作符
return 10 + 3, 22;
//运行+操作符
return 13, 22;
//运行 , 操作符
return 22;

现在让我们使用这些知识来看看如果我们不把这些变量放在括号里会发生什么:它有效的拥有最高的优先级。确保操作运算符优先执行:

//原始语句
var a = (7, 5);
// 执行组
var a = 5;
//原始语句
var a = 7, 5;
//运行 = 运算符
var a, 5; //a 现在等于7
//SyntaxError: missing variable name

通过将等号右边表达式放在括号里,我们创建了一个组 - 它有效的拥有最高的优先级。这个确保了逗号运算符能首先执行:

//原始语句
var a = (7,5);
//运行组
var a = 5;

在实践中,最低的运算符优先级确实使逗号操作符非常强大。事实上逗号操作符说:去吧,先去看看所有其他小的操作符,然后再来我这决斗结果。

一些语句中包含多个逗号。它们怎么运行的?

上面的规则仍然适用。在语句中每个逗号操作符从左到右有序的运行着。

var a = (1, 2, 3, 4);
a; //

这个等于:

var a = (((1, 2), 3), 4);
a; //

逗号用于文本类型和声明怎么样?

这些是逗号分隔符而不是逗号操作符。逗号分隔符的目的是将成员划分到列表中。例如:

//设置4个数组元素
var arr = [1, 2, 3, 4]; //创建拥有2个属性的对象
var obj = {
a: 22,
f: function(){return this.a * this.a}
} //定义3个不同的变量
var a = 1, b = 2, c = 3; // 调用一个函数并传递2个参数
Math.max(4, 7);

为什么使用逗号操作符?

因为他们让你指定多个表达式,而JavaScript预计只有一个。逗号操作符很少是必要的,但是通常很有用,偶尔地非常优雅:

 var r = [], n = 0, a = 0, b = 1, next;

 function nextFibonacici(){
next = a+b;
return b =(a=b, next);
} while(n++ < 10){
r.push(nextFibonacici();)
} r; //[1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
function getRandomPrime(){
while(n = Math.round(Math.random()*1000000000), !isPrime(n));
return n;
} var isPrime = function(n){
d = Math.ceil(Math.sqrt(n));
while(n%(d--) && d);
return !d;
} getRandomPrime(); //
getRandomPrime(); //

难道逗号操作符只是一个伪装的分号?

分号操作符分隔语句。逗号操作符分隔语句中的表达式。

为什么不使用逻辑与&&操作符来评估多个表达式的顺序?

逗号操作符是逻辑与&&和逻辑或操作符的亲密的表弟。三个操作符都会返回他们评估的最后一个表达式。他们的区别也简单:

 //(LHE: left hand expression,  RHE  right hand expression)

 LHE && RHE
1. 总是会执行左边的表达式
2. 如果左边是true,执行右边 LHE || RHE
1. 总是会执行左边表达式
2. 如果左边是false,执行右边 LHE, RHE
1. 总是执行左边表达式
2. 总是执行右边表达式

当两个表达式都必须要执行时,选择逗号操作符。

来点更多的例子咋样?

好的。前面我提到了逗号操作符使你指定多个表达式,而JavaScript只预定一个。这个或许是在for循环的范围:

for loops

这个是另外一个版本的斐波那契,也使用逗号操作符:

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

另一个例子,一个实用实例,帮助商品店员为客户选择钞票和硬币。下面是一个基本的版本。我们使用逗号操作符来等分for循环的第二个表达式。这使我们在测试限制表达式之前增加货币计算器:

function toCurrency(total, values){
total *= 100;
for(
var i =0, counts = [];
counts[i] = total/values[i], total = total % values[i];
i++); return counts.map(Math.floor);
} toCurrency(32.47, [500, 100, 25, 10, 5, 1]); //[6, 2, 1, 2, 0, 2]

现在下面是相同的实用实例,增加了对用户友好的格式:

function toCurrency(total, values, sym){
total *= 100;
// do the calc
for(
var i=0, counts = [];
counts[i]=total/values[i],total=total%values[i];
i++
);
//format
var results = counts.map(function(s,i){
return s>=1&&[Math.floor(s),"x",(sym || '$')+(values[i]/100).toFixed(2)].join(' ');
});
return results.filter(Boolean).join(', ');
}
toCurrency(19.77, [500,100,25,10,5,1]);
//"3 x $5.00, 4 x $1.00, 3 x $0.25, 2 x $0.01"
toCurrency(19.77, [500,100,50,20,10,5,1], '£');
//"3 x £5.00, 4 x £1.00, 1 x £0.50, 1 x £0.20, 1 x £0.05, 2 x £0.01"
toCurrency(19.77, [500,100,50,20,10,5,2,1], '€');
//"3 x €5.00, 4 x €1.00, 1 x €0.50, 1 x €0.20, 1 x €0.05, 1 x €0.02"

下面函数在一个for循环中使用逗号操作符来同时增加和减少两个计数器。计数器用来在控制台上渲染迷人的曲线:

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

while循环

你可以使用逗号操作符来创建一个简洁的do-while循环版本。搜索tag匹配的元素祖先。我们再次使用逗号来检查限制表达式:

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">

三元条件

三元语法允许每三个组件只有一个表达式。作为一般规则,如果你要使用多个声明,你需要考虑使用if else。然而有时在三元表达式中使用逗号操作符来比较简单的表达式更具有可读性:

//player loses
lives ? (lives--, go()):(gameOver(), exit());

调试

逗号操作符提供了一种低调的方式来注入console logs到你的代码中,而不必重新格式化(你能发现在每种情况下需要调试的错误吗?)。。。

//包含一个故意的错误!!!!
// 当i>n时输出总数
var i=10,n=0,total=0;
while(console.log(i,n),i-->n++);{
total += i*n
}
/*
10 0
9 1
8 2
7 3
6 4
5 5
24
*/
//包含一个故意的错误!!!!
// 总数是数组
var arr = [1,2,3];
for(
var i=0, total=0;
i<arr.length;
console.log(i,total), total += arr[i++]
);
/*
0 0
1 1
2 3
*/
//包含一个故意的错误!!!
//数组成员增加4,并求和
//(是的有更容易的方法来做到这一点)
var testArray = [3, 5, 8, 4], total = 0;
var plusFour = testArray.map(function(e){e + 4});
plusFour.forEach(function(n){console.log(n), isNaN(n) || (total += n)}); /*
undefined
undefined
undefined
undefined
*/

迭代器绑定

var colorIndex = 0,
colors = ["FF0000", "008000", "FF0086", "A2FF00", "0000FF", "800080"]; function selectNextColor(){
return colors[colorIndex++] || colors[colorIndex = 0, colorIndex++];
}

间接调用eval

eval1通常在他们包含上下文调用(例如在运算代码中的this值与周围代码的this值一样)。这是有问题的,因为无法保证重复的eval调用源于相同的上下文。

如kangax描述,我们可以使用时尚的逗号操作符来间接调用eval这将迫使它在全局上下文中执行2

var a = {};

//attempt eval in context of object <code>a</code>
(function() {
eval("this.alert('If you can read this I must be global!')");
}).call(a);
//TypeError: this.alert is not a function //force eval in global context
(function() {
(0,eval)("this.alert('If you can read this I must be global!')");
}).call(a);
//alerts: 'If you can read this I must be global!'

¹ eval的优点的讨论超出了本文的范围。

² 虽然ES5标准确认间接调用eval应该在全局范围内运行,但是不是所有浏览器都兼容(例如,IE<=8)。

总结

你可能没有使用逗号操作符,但可以写很好的JavaScript代码。这是否意味着我只是浪费了你的时间?我希望不是。正如一个广泛的词汇让我们成为更好的演讲者和作者,所以广泛的接触语言特征让我们成为更好的程序员。我们可支配的技术越多,我们就有更多的能力写出优雅、简洁的、可读的代码。

用逗号操作符编写有趣的代码,请分享你的整洁的用法示例!

https://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/

JavaScript 逗号操作符的更多相关文章

  1. JavaScript逗号操作符

    今天在CSDN看到一篇文章http://www.csdn.net/article/2014-01-06/2818025-Useful-JavaScript-Tips-Best-Practices?re ...

  2. 从头开始学JavaScript (五)——操作符(二)

    原文:从头开始学JavaScript (五)--操作符(二) 一.乘性操作符 1.乘法:*      乘法操作符的一些特殊规则: 如果操作数都是数值,按照常规的乘法计算,如果乘积超过了ECMAscri ...

  3. __VA_ARGS__与逗号操作符的巧妙结合

    class Test { public: template<class T> Test& operator,(T t) { //具体操作 return *this; } } Tes ...

  4. switch_case,&&,||,条件操作符和逗号操作符,循环语句

    一.switch-case switch-case语句主要用在多分支条件的环境中,在这种环境中使用if语句会存在烦琐且效率不高的弊端. switch(expression) { case const ...

  5. 从头开始学JavaScript (四)——操作符

    原文:从头开始学JavaScript (四)--操作符 一.一元操作符 1.自增自减操作符:分为前置型和后置型: 前置型:++a;--a; 后置型:a++;a--; 例: <script typ ...

  6. 坑:JavaScript 中 操作符“==” 和“===” 的区别

    标题:JavaScript 中 操作符"==" 和"===" 的区别 记录一些很坑的区别: 1. '' == '0' // false 0 == '' // t ...

  7. JavaScript中+操作符的特殊性

    在JavaScript中+操作符有两个作用: (1)加法运算 (2)字符串连接 在使用+操作符进行运算时,当+操作符两边都是数值类型的时候,进行加法运算; 当+操作符两边有任意一边是字符串,则进行字符 ...

  8. JavaScript剩余操作符Rest Operator

    本文适合JavaScript初学者阅读 剩余操作符 之前这篇文章JavaScript展开操作符(Spread operator)介绍讲解过展开操作符.剩余操作符和展开操作符的表示方式一样,都是三个点 ...

  9. ISO/IEC 9899:2011 条款6.5.17——逗号操作符

    6.5.17 逗号操作符 语法 1.expression: assignment-expression expression    ,    assignment-expression 语义 2.一个 ...

随机推荐

  1. File "<stdin>" , line 1

    写了一个hello.py,仅有一句,print 'hello world', 运行 Python hello.py 出错,提示: File "<stdin>" , li ...

  2. 在webconfig放置固定值

    通常的,为了布置到服务器后修改的方便通常把一些会改变的值放在webconfig: 首先在web.ocnfig中放入如下值 <appSettings> <add key="A ...

  3. iOS操作系统的层次结构

    iOS操作系统4层结构,如下表 可触摸层 Cocoa Touch layer 媒体层 Media layer 核心服务层 Core Services layer 核心操作系统层 Core OS lay ...

  4. 查询 request 对象的数据

    在 EmpController 中调用 RequestInfoService ris = new RequestInfoService(); ris.saveRequestInfo(request); ...

  5. Windows系统下Android开发环境搭建

    “工具善其事,必先利其器”.要想学好Android,搭建好Android开发环境是一个良好的开端. Windows系统下Android开发环境主要有4个大的步骤.分别是: 1.JDK的安装 2.ecl ...

  6. MySQL流程控制和存储过程介绍

    /*定义变量方式1:set @变量名=值;方式2:select 值 into @变量名;方式3:declare 变量名 类型(字符串类型加范围) default 值; in参数 入参的值会仅在存储过程 ...

  7. Linux OpenGL 实践篇-14-多实例渲染

    多实例渲染 OpenGL的多实例渲染是一种连续执行多条相同的渲染命令的方法,并且每条命令产生的结果都有轻微的差异,通常用于渲染大量的几何物体. 设想一个场景,比如太空,我们需要渲染数以万记的星球,如果 ...

  8. MDI和在TabPage

    无奈的.net探索 MDI和在TabPage中增加Form分页? MDI(Multiple Document Interface)是一种在窗口中嵌套窗口的接口, 与之对应的是SDI(Single Do ...

  9. 从汇编看c++中的多态

    http://www.cnblogs.com/chaoguo1234/archive/2013/05/19/3079078.html 在c++中,当一个类含有虚函数的时候,类就具有了多态性.构造函数的 ...

  10. 如何让浏览器关闭后session失效

    llzzcc66 知道合伙人数码行家 推荐于2018-08-10   如果用户不点击网站的“退出”链接,而直接关闭浏览器(或者强制关闭浏览器进程.死机等),服务器无法处理用户退出网站的请求,解决方式如 ...