JS操作符拾遗

栏目: JavaScript · 发布时间: 7年前

内容简介:对于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 属性。

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


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

查看所有标签

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

Data Structures and Algorithms

Data Structures and Algorithms

Alfred V. Aho、Jeffrey D. Ullman、John E. Hopcroft / Addison Wesley / 1983-1-11 / USD 74.20

The authors' treatment of data structures in Data Structures and Algorithms is unified by an informal notion of "abstract data types," allowing readers to compare different implementations of the same......一起来看看 《Data Structures and Algorithms》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

在线进制转换器
在线进制转换器

各进制数互转换器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具