这代码要是这样写会被打吧?类型操作趣题分享,学习堆JavaScript堆内存和栈内存

222 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

前言

最近吧,不是备战秋招所以在牛客上面刷题嘛,然后就发现了这神奇的一道题,不过还是有考察价值和值得学习的知识点的,我们来一起看看吧!😗

先来看看题 😛

请问以下JS代码输出的结果是什么?

let obj = {
  num1: 117
}
let res = obj;
obj.child = obj = { num2: 935 };
var x = y = res.child.num2;
console.log(obj.child);
console.log(res.num1);
console.log(y);

思考思考?

...

...

...

答案揭晓 🤨

undefined117935

OKOK,别生气,希望你拿起纸和笔,我们来逐行分析:

  1. let obj = { num1: 117 }

把obj放在栈里,把 { num1:117} 放在堆里,让obj指向堆里的 { num1:117 }

  1. let res = obj;

把res放在栈里,把res也指向堆里的 { num1:117 }

  1. obj.child = obj = { num2: 935 };

重点:赋值操作先定义变量(从左到右),再进行赋值(从右到左)

先定义变量:

定义变量:obj.child,给堆里的{ num1:117 }加一个child属性,得{num1:117,child:undefined}

定义变量:obj,之前在栈里的 obj

开始从右往左进行赋值:

赋值:obj = { num2: 935 },把 { num2: 935 } 放在堆里,把栈里的obj指向堆里的 { num2: 935 }

赋值:obj.child = obj,把堆里的 {num1:117,child:undefined} 的child指向 {num2: 935}

以上步骤完成后,我们此时有:

obj = { num2: 935 }

res = { num1: 117,child:{ num2: 935 } }

重复以上步骤,其中 y 则是全局变量:

  1. var x = y = res.child.num2;
console.log(obj.child);  // undefined
console.log(res.num1);  // 117
console.log(y);  // 935

补充:JavaScript 堆内存和栈内存

直接上图吧~,熟悉这块知识点内容的可以跳过了

image.png

  1. 基本类型,在内存中分别占有固定大小的空间(简单数据段),他们的值保存在栈空间,我们通过按值来访问。

  2. 引用类型,因为其大小不固定,通过栈内存中存放地址来指向堆内存中的对象,是按引用访问的。在栈内存中存放的只是该对象的访问地址,而在堆内存中为这个值分配空间。由于引用类型值的大小不固定,因此不能把它们保存到栈内存中,但其内存地址大小是固定的,因此可以将内存地址保存在栈内存中。

    当查询引用类型的变量时, 先从栈中读取内存地址, 然后再通过地址找到堆中的值。对于这种,我们把它叫做按引用访问。

题目来源:

牛客网

httpweixin.qq.comr5RGXj2jETTUyrSzs90T3.png

来源:前端妙妙屋 - 前端开发者的学习资源