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 属性。

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


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

查看所有标签

猜你喜欢:

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

MySQL技术内幕

MySQL技术内幕

姜承尧 / 机械工业出版社 / 2013-5 / 79.00元

《MySQL技术内幕:InnoDB存储引擎(第2版)》由国内资深MySQL专家亲自执笔,国内外多位数据库专家联袂推荐。作为国内唯一一本关于InnoDB的专著,《MySQL技术内幕:InnoDB存储引擎(第2版)》的第1版广受好评,第2版不仅针对最新的MySQL 5.6对相关内容进行了全面的补充,还根据广大读者的反馈意见对第1版中存在的不足进行了完善,《MySQL技术内幕:InnoDB存储引擎(第2......一起来看看 《MySQL技术内幕》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

MD5 加密
MD5 加密

MD5 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换