JS连续赋值与求值顺序

以下代码输出什么? 为什么?
var a = {n:1};
var b = a;
a = {n:2};
a.x = a ;
console.log(a.x);
console.log(b.x);
var a = {n: 1}
var b = a;
a.x = a = {n: 2};
console.log(a.x);
console.log(b.x)

  第一个问题:

a.x ---> {n:2,x:a};
b.x ---> undefined;

解答:a的值很清晰了,a第二次赋值以后变成了{n:2},随后添加了x属性指向自身。而对于b,在a第二次赋值以后,由于js中给变量赋值为object类型时,变量中存储的是对这个object的引用。此时,a指向{n:2} ,而b指向了{n:1} ,a和b指向不同的对象,因此,在a上添加属性对于b无影响,b.x自然就是undefined。

  第二个问题:

  解答:第三句里的主要难点在js运算符的优先级,访问属性、调用方法运算符"."的优先级高于赋值运算符。因此执行顺序是

  1. 给a添加属性x,此时a,b都是 { n:1,x:undefined },a.x 运算后的结果即为这个object(可以说也就是b)的x属性值。
  2. 把{n:2}赋值给a,此时a是 {n:2},是一个新的对象。 b是{ n:1,x:undefined }。

    由于( .  运算符最先计算)一开始js已经先计算了a.x,便已经解析了这个a.x是对象A的x,所以在同一条公式的情况下再回来给a.x赋值,也不会说重新解析这个a.x为对象B的x。

    所以 a.x=a 应理解为对象A的属性x指向了对象B:

    (这个时候a.x 已经运算完了,不会再与a产生任何关系,a.x依旧代表那个n为1对象的x属性值,和a已经没关系了。)

  3. 把{n:2}赋值给a.x 也就是 { n:1,x:undefined }这个对象的x属性,这个时候b依旧指向这个object,因此此时,a是{n:2},b是{n:1,x:{n:2}}
时间: 2024-10-11 18:26:21

JS连续赋值与求值顺序的相关文章

连续赋值与求值顺序var a = {n:1};a.x = a = {n:2}; alert(a.x);

代码如下: <script> var a = {n:1}; var b = a; a.x = a = {n:2}; console.log(a.x);// --> undefined console.log(b.x);// --> [object Object] </script> 上面的例子看似简单,但结果并不好了解,很容易把人们给想绕了——“a.x不是指向对象a了么?为啥log(a.x)是undefined?”.“b.x不是应该跟a.x是一样的么?为啥log出来居然

C之旅(一)运算符——优先级,结合性和求值顺序

本节主要讲基本运算符的优先级,结合性和求值顺序.先看一个表达式- (1 + 2) * 3 + (4 + 5 * (6 + 7 ))记住你对它的运算过程,看完下面的内容之后,也许你会用不同的方式来看待这个表达式. 基本运算符 = + - * / C中没有指数运算.运算符操作的是操作数,操作数就是放在运算符两侧的东西. (1) 赋值运算符 = year = 2016; 读作将值2016赋给year,而非year等于2016.=将2016赋给变量year,是从右到左的,即=具有右结合性.2016 =

C语言对表达式的求值顺序不是明确规定的

讨论区看到的 WA来自那些递归下降求解的代码. 第一种情况,使用|| 和 &&: 例如s为所给串 int getval() { switch(s[c_s++]) { case 'p': return (value & (1 << 0))? 1:0; case 'q': return (value & (1 << 1))? 1:0; case 'r': return (value & (1 << 2))? 1:0; case 's'

c++中函数参数的求值顺序

c++中如果函数的参数列表包含多个实参,那么对参数的求值顺序是不确定的. 在谭浩强的<C++程序设计>(第二版)P94中提到,GCC对参数求值是按从右到左的顺序求值的. 但我实测并非如此. #include <iostream> #include <iomanip> using namespace std; void test(int x, int y) { cout << 'x' << x << " y" <

Golang语句中的求值顺序

在Go specs中,有这样三点陈述: 1.变量声明(variable declaration)中的初始化表达式(initialization expressions)的求值顺序(evaluation order)由初始化依赖(initialization dependencies)决定:但对于初始化表达式内部的操作数的求值需要按照2中的顺序:从左到右: 2.在非变量初始化语句中,对表达式.赋值语句或返回语句中的操作数进行求值时,操作数中包含的函数(function)调用.方法(method)调

C++求值顺序

<C++Primer5th>中文版第124页 C++语言没有明确规定大多数二元运算符的求值顺序, 给编译器优化留下了余地. 这种策略实际上是在代码生成效率和程序潜在缺陷之间进行了权衡,这个是否可以接受? 1.首先可以知道优先级规定了运算对象的组合方式,但是没有说明运算对象按照什么顺序求值. 比如: int i=f1()*f2(); 在这里虽然f1和f2在乘法之前被调用,但是f1先调用还是f2先调用却不得而知. 2.再比如结合律: -- int i=0; cout<<i<<

表达式的求值顺序

代码: #include <stdio.h> #include <stdlib.h> #include <stdbool.h> // C语言保证逻辑表达式是从左至右求值 int main(void) { // printf("Left") == 4 // printf("Right") == 5 if (!printf("Left") && printf("Right")) 

二元运算符求值顺序问题

对于没有指定顺序的运算符来说,如果表达式指向并修改了同一对象,将会引发错误并产生未定义行为.如: int i = 0: cout << i << " " << ++i; // 未定义 经验: 拿不准时用括号 如果改变了一个运算对象的值,在表达式的其他地方就不要在使用这个运算对象(当改变运算对象的子表达式本身就是另外一个子表达式的运算对象时,是可以的 如:*++iter

关于C/C++ 表达式求值顺序 未定义

http://blog.csdn.net/zhongjiekangping/article/details/5164132 这篇文章讲的真好! 对于 "expr1 + expr2",(其中expr1,expr2都可能是复合表达式),不同的编译器想先算exp1就先算exp1,想先算exp2就先算exp2.而且,编译器不必保证exp1计算完毕之后才去计算expr2,它可以这么做,也可以不这么做.C语言标准里并不做规定. 一段正常的程序不应该由于加号前后的求解顺序不同而得到不同的结果.因此,