详解引用赋值操作符
JavaScript的堆栈
JavaScript的内存大致被分为两块,一块是栈区,一块是堆区
栈区里存放的是函数的栈帧,以及里面的临时变量
堆区则是放的对象,比如数组对象, 文件对象.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jHvHL13U-1649680956849)(C:\Users\31932\AppData\Local\Temp\1649678046306.png)]
=赋值操作符的使用与其返回值
A = B 表示将B的值赋给A
同时这个语句会返回一个B的值
var a = 10;
var b;
console.log(b=a); //10
console.log(b); //10
如果B是一个引用数据类型,则会返回其堆区的地址
console.log则会根据地址直接找回堆区
windows对象在JavaScript的特殊性
function fun() {
a = b = 5;
}
fun();
console.log(a, typeof a); //5 number
console.log(b, typeof b); //5number
b=3;
console.log(b, typeof b); //3 number
var b = 114514;
console.log(b);//114514
在c语言中,这样的代码是会报错的,因为a,b都是定义在函数内部的局部变量,为什么可以在全局中打出来呢?
因为script是属于windows全局对象里的一个属性,如果我们在函数内部声明了一个当前script里没有的变量,JavaScript就会默认在全局中创建这样一个变量,因此他就可以访问了
function fun() {
a = b = 5;
}
//在全局创建一个 a 一个 b
fun();
console.log(a, typeof a);
console.log(b, typeof b);
b=3;
//修改b
console.log(b, typeof b);
var b = 114514;
//如果我们主动声明了,就会删除原来的b,创建一个新b
console.log(b);
连等表达式的处理
var a = 2;
function fun(a) {
a = b = 5;
console.log(a, typeof a);
}
fun();
console.log(b, typeof b);
console.log(a,typeof a);
对于图上代码 f(a) =g(b) = h(c)的情况下,我们的规定是从左享向右处理
先处理f(a)中的东西,并将a挂起,再处理b的东西,再将b挂起,再处理c的东西,拿到c的返回值,赋值给b,再根据A=B的返回值特点将c的返回值再赋值给A
注意,一步一步来,分段处理,从左向右走!!!
var a = 2;
function fun(a) {
a = b = 5;
//先创一个A全局变量,a =等待赋值
//再创建一个b变量 b = 等待赋值
//5不需要执行
//执行赋值语句b 的值为5
//赋值语句执行结束,返回一个右操作数的值 5
//执行赋值语句,a的值变为5
console.log(a, typeof a);
}
fun();
console.log(b, typeof b);
console.log(a,typeof a);
引用数据类型的连等表达式处理
var a = {n:1};
var b = a;
a.x = a = {n:2};
console.log(a);
console.log(a.x);
console.log(b);
首先我们要,先知道对于一个{n:1}表示再堆区开辟对象,同时返回这个对象的地址。
现在我们逐步推进代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bod5ChkX-1649680956850)(C:\Users\31932\AppData\Local\Temp\1649679233823.png)]
一开始我们的栈区和堆区都是空的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AVFY1kSs-1649680956851)(C:\Users\31932\AppData\Local\Temp\1649679293452.png)]
第一条语句在堆区创建对象,并把他的地址赋值个在栈区新建的a;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vIrHDAv2-1649680956851)(C:\Users\31932\AppData\Local\Temp\1649679325412.png)]
第二条语句在栈区新建一个b,把a里的值赋给他
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RQVc1iWQ-1649680956852)(C:\Users\31932\AppData\Local\Temp\1649679470699.png)]
从左向右执行,先执行a.x,通过a里存的地址找到堆区的对象,在里面新建一个x属性,赋值为undefined
在执行 a,无事发生!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7KIMl5Gj-1649680956852)(C:\Users\31932\AppData\Local\Temp\1649679580361.png)]
在执行{n:2} 在堆去新建一个对象,他地址是0x5678
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lmhs9Utp-1649680956852)(C:\Users\31932\AppData\Local\Temp\1649679642874.png)]
开始执行赋值操作,把{n:2}的返回值—他的地址赋值给a,同时结束了赋值操作,返回等号右边的值0x5678
注意
最关键的一步来了,现在我们开始执行这个赋值表达式
因为上一步在执行f(a) : a.x 的时候,本是上是对这个式子进行了处理
这时这个赋值指针指向的是 前面找到的0x1234里的x属性
这时候把x属性赋值为 0x5678这个返回值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C0SQabEs-1649680956853)(C:\Users\31932\AppData\Local\Temp\1649680502790.png)]
现在执行第一条输出语句
console.log(a)
找出a对应的对象 0x5678
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KmdQfrtj-1649680956853)(C:\Users\31932\AppData\Local\Temp\1649680593682.png)]
再执行第二个语句
console.log(a.x)
因为a里没有x属性,所以返回默认值undefined
最后执行
console.log(b)
找出b对应的对象0x5678
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ajw0lTiU-1649680956854)(C:\Users\31932\AppData\Local\Temp\1649680720064.png)]
0956853)]
再执行第二个语句
console.log(a.x)
因为a里没有x属性,所以返回默认值undefined
最后执行
console.log(b)
找出b对应的对象0x5678
[外链图片转存中…(img-ajw0lTiU-1649680956854)]
完成啦!