JavaScript 逗号操作符
让我们从一个有趣的微博开始吧。

末尾的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 逗号操作符的更多相关文章
- JavaScript逗号操作符
今天在CSDN看到一篇文章http://www.csdn.net/article/2014-01-06/2818025-Useful-JavaScript-Tips-Best-Practices?re ...
- 从头开始学JavaScript (五)——操作符(二)
原文:从头开始学JavaScript (五)--操作符(二) 一.乘性操作符 1.乘法:* 乘法操作符的一些特殊规则: 如果操作数都是数值,按照常规的乘法计算,如果乘积超过了ECMAscri ...
- __VA_ARGS__与逗号操作符的巧妙结合
class Test { public: template<class T> Test& operator,(T t) { //具体操作 return *this; } } Tes ...
- switch_case,&&,||,条件操作符和逗号操作符,循环语句
一.switch-case switch-case语句主要用在多分支条件的环境中,在这种环境中使用if语句会存在烦琐且效率不高的弊端. switch(expression) { case const ...
- 从头开始学JavaScript (四)——操作符
原文:从头开始学JavaScript (四)--操作符 一.一元操作符 1.自增自减操作符:分为前置型和后置型: 前置型:++a;--a; 后置型:a++;a--; 例: <script typ ...
- 坑:JavaScript 中 操作符“==” 和“===” 的区别
标题:JavaScript 中 操作符"==" 和"===" 的区别 记录一些很坑的区别: 1. '' == '0' // false 0 == '' // t ...
- JavaScript中+操作符的特殊性
在JavaScript中+操作符有两个作用: (1)加法运算 (2)字符串连接 在使用+操作符进行运算时,当+操作符两边都是数值类型的时候,进行加法运算; 当+操作符两边有任意一边是字符串,则进行字符 ...
- JavaScript剩余操作符Rest Operator
本文适合JavaScript初学者阅读 剩余操作符 之前这篇文章JavaScript展开操作符(Spread operator)介绍讲解过展开操作符.剩余操作符和展开操作符的表示方式一样,都是三个点 ...
- ISO/IEC 9899:2011 条款6.5.17——逗号操作符
6.5.17 逗号操作符 语法 1.expression: assignment-expression expression , assignment-expression 语义 2.一个 ...
随机推荐
- php post提交超过1000个字段的时候服务器会截断多余部分
采取将子字段转化为json的形式,合并多个字段于一个字段
- 禁用和关闭ECSHOP缓存
ECSHOP的缓存机制从一定程度上可以减少ECSHOP反复读取数据库的几率,从而一定程度上降低服务器负担,提高访问速度. 但是启用缓存机制,对一些新手站长也有不利的地方.我就遇到很多新手站长经常问,我 ...
- httpd.exe占用100%CPU
客户VPShttpd.exe进程占用100%CPU百度搜了下,很多文章: 在网上也没有能够直接找到比较好的解决方法,后来在一个帖子上看到说,有可能是apache与其他的软件冲突了(参考http://t ...
- 两小时学Thinkphp3.1(多数来自thinkphp3.1快速入门)
调试模式 define('APP_DEBUG',TRUE); 定义自动验证 protected $_validate = array( array('title','require','标题必须'), ...
- Java MVC 增删改查 实例
需求:实现增加新部门的功能,对应数据库表示Oracle的dept表 一.Java MVC 增 实现: 1.视图层(V):注册部门 deptAdd.jsp 在注册新部门页面只需输入“部门名称”和“城市” ...
- Clown without borders 2017/1/9
原文 Taking laughter to those who need it most "When will you all return again?"the Croatian ...
- 洛谷 P2264 情书
题目背景 一封好的情书需要撰写人全身心的投入.lin_toto同学看上了可爱的卡速米想对她表白,但却不知道自己写的情书是否能感动她,现在他带着情书请你来帮助他. 题目描述 为了帮助lin_toto,我 ...
- (五)maven之外置maven
eclipse外置maven eclipse内置的maven插件是固定版本,如果要用其他版本的maven,可以使用外置maven. ① 在菜单栏上点击“Windows”à“Preferences ...
- Chrome浏览器扩展程序的本地备份
由于众所周知的原因,有些朋友可能很难在线下载Chrome扩展程序.一种选择是可以让朋友把他成功安装的Chrome扩展程序导出成本地文件,然后让朋友发送给自己,在自己本地电脑上报这些本地文件直接拖到Ch ...
- halcon相机标定及图像矫正
https://blog.csdn.net/humanking7/article/details/44756073 相机标定内容详解:转载自 祥的博客 预备知识 标定中的四个坐标系 1.1.平面旋转 ...