JS操作符拾遗
栏目: JavaScript · 发布时间: 5年前
内容简介:对于js操作符的一些特性和有趣题目的整理。逗号操作符有两个作用,一个是用于当你想要在期望一个表达式的位置包含多个表达式时,可以使用逗号操作符。这个操作符最常用的一种情况是:for 循环中提供多个参数。另一个使用逗号操作符的例子是在返回值前处理一些操作。如同下面的代码,只有最后一个表达式被返回,其他的都只是被求值。赋值多个变量用
前言
对于js操作符的一些特性和有趣题目的整理。
逗号操作符
逗号操作符有两个作用,一个是用于当你想要在期望一个表达式的位置包含多个表达式时,可以使用逗号操作符。这个操作符最常用的一种情况是:for 循环中提供多个参数。另一个使用逗号操作符的例子是在返回值前处理一些操作。如同下面的代码,只有最后一个表达式被返回,其他的都只是被求值。
function myFunc () { var x = 0; return (x += 1, x); // the same of return ++x; }
赋值多个变量用 var a = 3, b = 4, c = 5;
和 var a = 3; var b = 4; var c = 5;
本质并没有什么不同,只是一种编码习惯,用知乎上一位朋友的话说,前者是 高耦合,低冗余
,后者是 低耦合,高冗余
,后者更严谨一点,在维护的时候也不容易出错。
关于逗号的第二个用法,有时会引起一些现象,比如下面的代码就改变了函数中的this指向,因为表达式 (0, obj.fun)
返回了 obj.fun
的引用,相当于window调用这个函数,所以 this
发生了变化:
var obj = { fun: function () { console.log(this); } } obj.fun(); //输出obj (0, obj.fun)() //输出window对象
链式赋值
我的赋值是可以用链式的方法把一个值赋值给多个变量,当所有变量都被声明,这样做并没有什么问题,但是如果是函数作用域内这样做有时候会引起一些奇怪的现象:
function test() { var a; a = b = 3; } test(); console.log(b); //3 console.log(a); //报错
从结果我们可以看出 b
成为了一个全局变量,要明白原因我们先要知道js引擎是如何解析 a = b =3;
这条表达式的,我们知道赋值是基于右值的值给左值赋值。根据这个规则我们可以知道,引擎的第一步是把 a
当作左值, b = 3
当作右值,因为 b = 3
是一个表达式,算出值以后才能赋值,所以计算 b = 3
的值,此时引擎发现变量 b
并没有声明,也就是在当前执行环境的变量对象找不到这个变量,于是 b
被处理成了 var b = 3
,成了一个全局变量。
变量声明提前不能跨 <script>
标签,更不能跨文件,也就是说变量提升仅仅是把当前js文件或标签中的 var
声明变量或 function
的声明提升到当前文件或标签的开头。并且当函数和变量重名的时候,被提升的声明会是函数。
上面的代码赋值表达式的右值都是js的基本类型,如果右值是对象的时候,情况会更复杂一些。因为对象被保存在堆中,我们对对象的赋值只是把对象的引用赋值给变量,而引用的变化不会引起对象的变化,堆中的对象不会因为变量之间引用的传递而发生改变,记住这一点就不太容易被迷惑。不过有时候情况比我们想象的还要复杂一下,比如下面这道经典的题目:
var a = {n: 1}; var b = a; a.x = a = {n: 2}; console.log(a.x);//undefined console.log(b.x);//{n: 2};
如果用上面那一套方式来想这道题,第一步左值为 a.x
,右值为 a = {n: 1}
,第二步计算 a = {n: 2}
,左值为 a
,右值为 {n: 2}
,把 {n: 2}
的引用给 a
就可以了,然后赋值给第一步的左值,得到结果 a.x = {n: 2}
。流程其实没什么问题,但是在第一步的时候忘记一件事,就是 a对象并没有x属性
,而且 .
运算符的优先级是仅次于括号的,在还没开始进行赋值分析的时候,已经对 a.x
进行了处理,就是在 a
对象中加入 x
属性,虽然此时并没有对该属性初始化, a.x
应该为 undefined
。有了这个思路我们再按刚才的流程走一遍,当完成第二步 a = {n: 2}
的时候 a
的引用已经改变,此时 a.x
代表的是 {n:1, x: undefined}
中的 x
(可能有人疑惑 a
已经改变引用, a.x
中的 a
应该也变了,但因为 a.x
和 a
在同一个表达式内, a.x
已经在前面被引擎解析, a.x
此时应被理解成堆中对象的属性),最后把这个 {n: 2}
的引用赋给 x
属性。
我们可以发现赋值运算的解析是从左向右,但是计算是从右向左的。链式赋值有时候会遇到这样的副作用,所以还是尽量避免使用。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Android RxJava 操作符详解系列:条件 / 布尔操作符
- C语言中点操作符(.)和箭头操作符(->)的不同之处
- JavaScript骚操作之操作符
- MongoDB拾遗(一)
- js 拾遗
- 迁移 Nexus 软件仓库拾遗
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
C#入门经典
[美] Karli Watson、Christian Nagel / 齐立波、黄静 / 清华大学出版社 / 2008-12 / 118.00元
这是一本成就无数C#程序员的经典名著,厚而不“重”,可帮助您轻松掌握C#的各种编程知识,为您的职业生涯打下坚实的基础,《C#入门经典》自第1版出版以来,全球销量已经达数万册,在中国也有近8万册的销量,已经成为广大初级C#程序员首选的入门教程,也是目前国内市场上最畅销的C#专业店销书,曾两次被CSDN、《程序员》等机构和读者评选为“最受读者喜爱的十大技术开发类图书”!第4版面向C#2008和.NET......一起来看看 《C#入门经典》 这本书的介绍吧!