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.xa 在同一个表达式内, a.x 已经在前面被引擎解析, a.x 此时应被理解成堆中对象的属性),最后把这个 {n: 2} 的引用赋给 x 属性。

我们可以发现赋值运算的解析是从左向右,但是计算是从右向左的。链式赋值有时候会遇到这样的副作用,所以还是尽量避免使用。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C#入门经典

C#入门经典

[美] Karli Watson、Christian Nagel / 齐立波、黄静 / 清华大学出版社 / 2008-12 / 118.00元

这是一本成就无数C#程序员的经典名著,厚而不“重”,可帮助您轻松掌握C#的各种编程知识,为您的职业生涯打下坚实的基础,《C#入门经典》自第1版出版以来,全球销量已经达数万册,在中国也有近8万册的销量,已经成为广大初级C#程序员首选的入门教程,也是目前国内市场上最畅销的C#专业店销书,曾两次被CSDN、《程序员》等机构和读者评选为“最受读者喜爱的十大技术开发类图书”!第4版面向C#2008和.NET......一起来看看 《C#入门经典》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

html转js在线工具
html转js在线工具

html转js在线工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具