值得深思的连续赋值--赋值运算符运算顺序

最近在看到以前前辈留下的文章,对于连续赋值( var a={n:1}; a.x=a={n:2}) )这个知识点,一开始也搞不清楚,但是最终还是说服了自己,谈谈自己的心得。以下代码能回答正确的可以忽略本文。

1 var a={n:1};
2 var b=a;
3 a.x = a = {n: 2};
4 console.log(a.x); //?
5 console.log(b.x);//?

正确答案是:

a.x= undefined;
b.x= {n: 2};

疑惑:为什么a.x与b.x不相等呢?为什么a.x会等于undefined呢?

如果你答错了,那么请你往下看。



javascript中的引用赋值

很清楚的一点是:js中对象的赋值其实是引用的赋值,只是将b对象的引用指针指向了a对象的引用。

1 var a={n: 1};
2 var b= a;
3 console.log(b.n); // 1
4 a.n=2;
5 console.log(b.n); // 2

上面的代码对于一个程序员来说应该都没有理解上的问题。



赋值运算符的右结合

也就是说赋值运算符是从右向左运算的,这个倒不难理解,例如 var a = 1 + 2; 先计算了等号右边1+2,将右边的结果3赋值给了a;当然你也许会说这是运算符的优先级;其实这里本文想要表达的是赋值运算是将“=”右边赋值给左边。下面这个例子应该会更加帮助你理解。

1 var a, b;
2 a=b=1+2;

其中按照赋值运算符的右结合的特质:

a = b = 1 + 2 等价于 a = (b= 1+2 )

其中 b 等于 1+2的返回值 3 ;

a 等于 b=3 的返回值 3;



赋值运算符运算顺序:从左到右

虽然上面讲到赋值运算符是从右向左运算的,但是其运算顺序是从左往右的。也就是说本文一开始提出的问题 a.x = a = {n:2} 是从左向右运算的(赋值是从右向左);也就是说程序的计算顺序是:

1 a.x
2 a
3 {n:2}

程序执行到 a.x = a = {n:2} 先执行a.x 并等待赋值符号“=”后面的运算返回值;然后执行a并等待赋值符号“=”后面的运算返回值。



答案是这样来的

如果看到这有点绕进去了,分析一下本文一开始提出来的例子应该会帮助你更好地了解:

1 var a={n:1};
2 var b=a;
3 a.x = a = {n: 2};

1. 变量a指向了一个对象{n:1};

2. 变量b指向了a的引用(其实就是{n:1});

3. 计算a.x并等待赋值符号“=”后面的运算返回值(此时,a指向的是{n:1});

4. 计算a并等待赋值符号“=”后面的运算返回值,注意这里将a的引用指向了{n:2};

到这里你是否看出了,第3步a.x的a是{n:1};第4步的a已经被改成了{n:2};

因此当console.log(a.x)的时候就肯定是undifined了;而console.log(b.x)为{n:2};

如果到这里还不明白,不妨再增加两个变量 obj1, obj2; 令obj1={n:1}; obj2={n:2}

1 var obj1={n:1};
2 var obj2={n:2};
3 var a=obj1;
4 var b=a;
5 a.x=a=obj2;
6 console.log(a.x); //undefined
7 console.log(b.x); //{n:2}
8 console.log(obj1); //{n:1, x:{n:2}}
9 console.log(obj2); //{n:2}

其实 a.x=a=obj2 等价于

a=obj2;

obj1.x=obj2;



作者:AlvinWei  文章出处:韦躐晟的博客 http://www.cnblogs.com/alvinwei1024/p/4856623.html

本文版权归作者和博客园共有,欢迎转载

转载请说明原文章出处



最后

写代码时要搞清楚变量间的引用关系,一般情况下不要写这种容易误导自己和他人的代码。我想这种情况一般只会出现在面试题里,用来考核对基础知识的掌握度。

时间: 2024-08-06 11:51:29

值得深思的连续赋值--赋值运算符运算顺序的相关文章

java中+(加号或字符串连接)运算顺序的问题

由于java中+(加号或字符串连接)的运算顺序是从左向右的,所以一下程序的输出会得到两个不同的结果 1 public class Test { 2 public static void main(String[] args) { 3 System.out.println("ddd"+7+5); 4 System.out.println(7+5+"ddd"); 5 6 } 7 } 结果为ddd75 12ddd

运算顺序引发的一系列有趣问题

问题:采用递归方法计算给定整型数组元素之和. 以下给出几种递归算法的实现: 1 int sum1(int a[], int n) 2 { 3 if(n > 0) 4 return a[n-1] + sum1(a, n-1); 5 else 6 return 0; 7 } 8 9 int sum2(int a[], int n) 10 { 11 if(n > 0) 12 return a[n-1] + sum2(a, --n); 13 else 14 return 0; 15 } 16 17 i

java 运算顺序

java 运算顺序,布布扣,bubuko.com

C语言中指针和自增运算符结合时的运算顺序问题

在C语言中,当指针运算符和++或者–结合时很容易分不清运算顺序,在这里总结一下,下面一共分析6中组合: * p++,(* p)++,* (p++),++* p,++( * p), * (++p). 先看段代码以及输出: #include<stdio.h> int main() { int a[3]={1,3,5}; int *p=a; printf("----------------1----------------\n"); printf("%d\n"

js 关于运算顺序的问题

先介绍涉及到的概念 表达式:js中的短语,解释器在遇到表达式时,会将短语进行计算,然后再参与到运算中,表达式即js中的短语. j所有的s代码都是由操作符和表达式组成的,因此除了操作符,其他的都是js中的表达式. 如1 + 1 这段代码中,+是操作符,前面的1和后面的1都是表达式. 表达式的分类: 原始表达式:常量(如π).变量.直接量(数字.字符串.正则表达式).关键字 初始化表达式:初始化对象和初始化数组 函数定义表达式: 函数调用表达式: 属性访问表达式: 对象创建表达式:使用new操作符创

js运算顺序随笔

看代码看到一个js多运算符运算.自己写代码试了一下明白了. 自己示范的代码 运算顺序,先是非用算a的非为false,然后进行严格等于运算.b===false为false.再进行逻辑或运算两个都是falses所以不会进入if语句,不会弹框 原文地址:https://www.cnblogs.com/w7589/p/8274835.html

javascript:第四章 &nbsp; Number 和 parseFloat 和 parseInt &nbsp; 的运算顺序注意的!

Number 的 运算是 从整体把么个参数转成number类型 alert(Number(''));//0 //alert(Number([]));//0 alert(Number('20元')):=>NaN alert(Number(null));=>0; alert(Number(document));=>NaN; alert(Number(NaN));=>NaN; alert(Number(true));=>1; alert(Number(undefined));=&g

Python中 and or 运算顺序详解 --- 短路逻辑

核心思想 表达式从左至右运算,若 or 的左侧逻辑值为 True ,则短路 or 后所有的表达式(不管是 and 还是 or),直接输出 or 左侧表达式 . 表达式从左至右运算,若 and 的左侧逻辑值为 False ,则短路其后所有 and 表达式,直到有 or 出现,输出 and 左侧表达式到 or 的左侧,参与接下来的逻辑运算. 若 or 的左侧为 False ,或者 and 的左侧为 True 则不能使用短路逻辑. 详情参见:http://www.cnblogs.com/an9wer/

C语言运算符运算顺序判断实例2

#include <stdio.h> int main(void) { int i = 1, j = 1, k = 1; printf("%d\n", ++i || ++j && ++k); printf("%d %d %d\n", i, j, k); } 运行结果为: 1 2 1 1 左边算子优先计算 ++i = 2 被下一个 printf 读取,|| 符号只会储存左边的运算值,右边新计算的值被遗弃. 如果程序变为: #include