ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

JS Tips 第 57 期:JavaScript 逗号运算符(Comma Operator)——在单条语句中顺序执行多个表达式

JS Tips 第 57 期:JavaScript 逗号运算符(Comma Operator)——在单条语句中顺序执行多个表达式 教程【免费下载链接】jstipsThis is about useful JS tips!项目地址https://gitcode.com/gh_mirrors/js/jstips点击查看免费下载逗号运算符,是 JavaScript 中最易被忽视、却最常出现在循环与链式表达式中的运算符之一。本篇文章基于 jstips 仓库中的 2016-08-10-comma-operaton-in-js.mdTip #57展开结合仓库内其他相关技巧系统讲解逗号运算符的求值规则、在for循环与表达式中的典型用法、它与赋值、短路求值等运算符的相互作用以及新手最容易踩中的优先级陷阱。读完本文你将能准确预测含逗号运算符的表达式的执行顺序与最终返回值并能在循环、函数返回值等场景中安全地使用它。一、逗号运算符不只是分隔符在绝大多数场景中逗号只是语法层面的分隔符例如声明多个变量、定义多个参数、调用函数时传递多个实参var a 1, b 2; // 变量声明中的分隔符 function f(x, y) { ... } // 参数列表中的分隔符 f(a, b); // 实参列表中的分隔符但逗号还有一个常被忽略的身份——运算符。作为运算符时它允许你在只期望一条语句或一个表达式的位置上放入多个表达式。用原文档的话说Apart from being just a delimiter, the comma operator allows you to put multiple statements in a place where one statement is expected.除了作为分隔符逗号运算符还允许你在只期望一条语句的位置放置多条语句。两者的本质区别在于分隔符只是把若干项并列在一起不参与求值而逗号运算符会真正参与运算产生一个确定的结果。二、for 循环中的经典用法多个初始化与步进表达式逗号运算符最常见的实战场景就是for循环的初始化与更新部分。由于for的语法规定每个位置只能写一条语句而逗号运算符恰好可以合并多条语句因此可以这样写for(var i0, j0; i5; i, j, j){ console.log(i:i, j:j); }输出i:0, j:0 i:1, j:2 i:2, j:4 i:3, j:6 i:4, j:8逐行拆解这段代码初始化区var i0, j0注意这里的逗号是变量声明的分隔符var声明的一部分它同时声明并初始化i与j更新区i, j, j这里的逗号才是逗号运算符。每轮循环结束后按从左到右的顺序依次执行i、j、j所以j每轮递增 2而i每轮递增 1条件区i5控制循环 5 轮于是j依次为 0、2、4、6、8与输出完全吻合。这正是逗号运算符在单个位置编排多个操作能力的直接体现。与之相关仓库中的 2016-02-04-assignment-shorthands.mdTip #35专门讲解了/--前后置递增递减的语义差异与循环步进配合使用可以写出更紧凑的迭代逻辑。三、表达式中的求值规则从左到右返回最右逗号运算符真正的行为规则只有一句话对每个操作数按从左到右的顺序依次求值并返回最右边的那个表达式的值。原文档用三个函数演示了这一规则function a(){console.log(a); return a;} function b(){console.log(b); return b;} function c(){console.log(c); return c;} var x (a(), b(), c()); console.log(x); // Outputs c输出a b c c可以看到a()、b()、c()依次被调用副作用console.log按顺序全部发生因此先打印a、b、c整个(a(), b(), c())表达式的最终值是最右边的c()的返回值c因此x等于c随后打印的c就是x的值。也就是说逗号运算符不会像或||那样提前短路它总是把左侧所有表达式都求值完再取最后一个值作为结果。四、优先级陷阱括号为何必不可少原文档特别强调了一条关键注意事项逗号,运算符是所有 JavaScript 运算符中优先级最低的所以不加括号时表达式会变成(x a()), b(), c();。这条陷阱值得展开解释。上面的例子中var x (a(), b(), c());因为括号的存在先计算逗号表达式得到c再赋值给x。但如果去掉括号写成var x a(), b(), c();由于逗号运算符的优先级低于赋值运算符实际会被解析为(x a()), b(), c();即先执行x a()x被赋值为a然后依次求值b()、c()——c()的返回值c是整个语句的值但这个值不会赋给x。结果x是a而不是c行为完全变了。这解释了为什么在所有需要把逗号表达式的结果赋给变量、传给函数或作为条件判断的场景中都必须用括号把逗号表达式括起来。同理如果希望用逗号表达式的返回值做条件判断如while循环也要写成while ((row readRow(), row ! null))这样的形式。五、与其他运算符的对照逗号、短路求值与赋值要真正掌握逗号运算符最好把它放在运算符家族的坐标系中看待。仓库中与之关系最密切的是 2016-01-27-short-circuit-evaluation-in-js.mdTip #27讲解的短路求值与||会有条件地跳过右侧表达式而逗号运算符则无条件求值所有操作数。三者的返回值差异可以总结如下运算符求值行为返回值,从左到右全部求值最右侧操作数的值左侧为 falsy 时短路最后一个被求值操作数的值||左侧为 truthy 时短路最后一个被求值操作数的值求值右侧并写入左侧赋值后的值可链式赋值而 2016-02-13-know-the-passing-mechanism.mdTip #44则从另一个角度提醒我们当逗号表达式中的副作用涉及对象引用修改时要留意 JavaScript 按值传递的语义避免把顺序求值误当作作用域穿透。六、常见应用场景在了解规则与优先级之后逗号运算符在下列场景中是合法且惯用的1. 循环步进中同步更新多个计数器即第二部分展示的for(var i0, j0; ...; i, j)写法。配合 2016-08-17-break-continue-loop-functional.mdTip #58中关于循环终止的讨论你可以在循环体内自由使用break/continue控制流程同时保持步进表达式紧凑。2. 在单条表达式中按顺序执行多个副作用例如把多条日志或状态更新塞进一个表达式function handle() { return (log(start), doWork(), log(done), result); }这里log、doWork按顺序执行最终返回result。3. 函数式工具中返回累加器在Array.prototype.reduce的回调里可以利用逗号运算符在返回累加器的同时执行额外逻辑const sum arr.reduce((acc, n) (acc.push(n * 2), acc), []);acc.push(...)返回新长度而逗号表达式取最右侧的acc作为返回值正好满足reduce对返回累加器的要求。4. 条件表达式中的多操作与三目运算符结合可以在单行内完成执行多个动作并取最后值const status ok ? (save(), saved) : (warn(), failed);七、使用要点与易错点小结作用域内顺序求值逗号运算符保证所有操作数从左到右依次求值任何一侧的副作用函数调用、赋值、日志都会发生结果只取最右整个表达式的值等于最后一个操作数的值左侧操作数的返回值被丢弃优先级最低在赋值、条件、调用等复合场景中必须加括号否则会按(x a()), b(), c()的方式被解析区分分隔符与运算符var a1, b2中的逗号是声明语法的一部分函数调用的实参列表f(a, b)中的逗号也只是分隔符它们都不产生取最右值的语义可读性优先逗号运算符适合在for步进等约定俗成的场景使用在业务逻辑中大量使用会让代码难以阅读此时应优先考虑拆分为多行语句或使用块级逻辑。八、仓库中的关联资源本文对应原文档2016-08-10-comma-operaton-in-js.mdTip #57作者 bhaskarmelkani逗号运算符常与短路求值并列出现short-circuit-evaluation-in-js.mdTip #27循环控制与提前终止break-continue-loop-functional.mdTip #58赋值与自增自减简写assignment-shorthands.mdTip #35全部技巧索引见 README.md如果你想为这个系列贡献新的技巧可以参考 POST_TEMPLATE.md 与 CONTRIBUTING.md。赞分享教程【免费下载链接】jstipsThis is about useful JS tips!项目地址https://gitcode.com/gh_mirrors/js/jstips点击查看免费下载相关推荐jstips 第 57 期精讲JavaScript 逗号操作符Comma Operator的求值规则与实战用法jstips 第 57 期精讲JavaScript 逗号操作符Comma Operator的求值规则与实战用法 逗号操作符Comma Operator教程JavaScript 三元运算符Ternary Operator完整指南条件表达式的 if 语句快捷方式JavaScript 三元运算符Ternary Operator完整指南条件表达式的 if 语句快捷方式 导读 三元运算符ternary operato教程OpCore Simplify一份硬件报告生成可用的黑苹果 EFI 完整指南OpCore Simplify一份硬件报告生成可用的黑苹果 EFI 完整指南 先说结论OpCore Simplify 是一款黑苹果 EFI 自动生成工具把开发工具CLI上一篇Atom 内置 Base16 Tomorrow Dark 语法主题详解Base16 色板体系、Less 文件结构与主题加载机制下一篇rxjs/observable-polyfill 深度解析RxJS 9 的 Web 平台 Observable 条件回退实现创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表