为了转生而点技能-JavaScript,day7 (原始型态与物件型态在记忆体上的变化

前言:这篇文希望可以让自己更了解原始型态与物件型态在记忆体的Stack跟Heap上的变化,并了解物件内部的属性及值在不同情况下的移动路径。

记忆体(memory)分两区:http://img2.58codes.com/2024/20143762s9LjqrAEdP.png

Stack:主要是放置变数及函式陈述式(具名函式)的名字、原始型(primitive type)的地方。

Heap Memory:主要放置函式陈述式(具名函式)的function()、Reference Type。
http://img2.58codes.com/2024/20143762yZlO4ck3cy.png

变数、函式、物件在记忆体中的位置及堆叠变化

http://img2.58codes.com/2024/20143762fWQkXrG5Nm.jpg
http://img2.58codes.com/2024/20143762b6T8WKORl8.jpg
http://img2.58codes.com/2024/20143762ARK1VD9UPm.jpg
图片来源:V8 Memory usage(Stack & Heap)

1. 当变数被赋予纯值(七个原始型)时:会在记忆体上的Stack区标记储存的地址及值。

       var myNumber = 23

http://img2.58codes.com/2024/20143762Up2otzi0Nd.jpg

当变数当成值并LHS到另一变数上时,原变数的值已经存在记忆体上,只是将地址给予新的变数,所以原来的变数值不会有任何变化。
        var myNumber = 23        var newVar = myNumber        console.log(myNumber);  //23        console.log(newVar);    //23

http://img2.58codes.com/2024/20143762SzmHrBXfDP.jpg

        var myNumber = 23;        var newVar = myNumber;        myNumber = myNumber + 1;        console.log(myNumber);  //24        console.log(newVar);    //23

http://img2.58codes.com/2024/20143762Q4vY3Svbdk.jpg

2.当变数被赋予物件型态时:会在记忆体上的Stack区标记储存的地址、值(为放在Heap Memory内容的address)。

var myArray = [];

http://img2.58codes.com/2024/20143762gQ64GENaQs.jpg


如果新变数重新更新了旧物件里面的属性之值,旧变数赋值给新变数,而值是Heap Memory内容的address,值(address)都一样,但是Heap Memory的内容已经发生改变,导致旧变数物件的属性之值也跟着一起更新。

        var person = {            name: '小名',            money: '500',        };        console.log(person.name); //'小名'
        var person = {            name: '小名',            money: '500',        };        var person2 = person;        console.log(person.name);  //'小名'        person2.name = '杰伦';     //更新了物件里属性:name 里面的值:'小名'->'杰伦'        console.log(person.name);  //'杰伦'        console.log(person2.name); //'杰伦'        console.log(person2 === person); //true

http://img2.58codes.com/2024/201437625JuWwKRkUv.jpg

        var person = {            name: '小名',            money: '500',        };        var person2 = person;        person2= {            name: '小名',            money: '500',        };        console.log(person.name);  //'小名'        console.log(person2.name); //'小名'        console.log(person2 === person); //false

console.log(person2 === person); //false
解:
因为person2变数重新创造了一个物件,导致Heap Memory内容的address跟person不同,即person有1个adress,person2有1个adress(2),adress不同代表值不同,所以false。


3.例子1:

        var family = {                //变数family;值是adress01            name: '小明家',           //属性name;值是小明家;存在heap memory的aderss01。            members: {               //属性members;值是adress02                father: '老爸',      //属性father;值是老爸;存在heap memory的aderss02。                mom: '老妈',                ming: '小明'            },        };        var member = family.members; //将值adress02赋予新变数member。        console.log(member, family.members);// member === family.members

http://img2.58codes.com/2024/20143762zGwaF4mE1x.jpg

        var family = {                //变数family;值是adress01            name: '小明家',           //属性name;值是小明家;存在heap memory的aderss01。            members: {               //属性members;值是adress02                father: '老爸',      //属性father;值是老爸;存在heap memory的aderss02。                mom: '老妈',                ming: '小明'            },        };        var member = family.members; //将值adress02赋予新变数member。        member = {            ming: '大明',        };                           //新变数member重新设立新的物件,值是adress03        console.log(member, family.members);  //大明,小明

http://img2.58codes.com/2024/20143762zfuJCG47a8.jpg


        var family = {                //变数family;值是adress01            name: '小明家',           //属性name;值是小明家;存在heap memory的aderss01。            members: {               //属性members;值是adress02                father: '老爸',      //属性father;值是老爸;存在heap memory的aderss02。                mom: '老妈',                ming: '小明'            },        };        var member = family.members; //将值adress02赋予新变数member。        member.ming = '大明';        //将属性ming的值变更为大明        console.log(member, family.members);    // 大明,大明        console.log(member === family.members); //true,因为值都是adress02

http://img2.58codes.com/2024/201437622N52S1vI7T.jpg


例子2:

        var a = { x: 1 };        var b = a;        a.y = a = { x: 2 };        console.log(a.y);        console.log(b);

1. var a = { x: 1 };var b = a;

http://img2.58codes.com/2024/201437627EhUQ1y0LN.jpg
####2. a.y = a = { x: 2 };
**注意!!**此步骤是同时进行,意思为 a = { x: 2 }与a.y = { x: 2 }是同时进行。
a = { x: 2 }: 创立新的物件,adress是adress02,并且赋予值(adress02)给变数a。
http://img2.58codes.com/2024/20143762bHPA6AopAR.jpg
a.y = { x: 2 }:创立新的物件,adress是adress02;在变数a,值为adress01的物件里创立属性为y且值为adress02。
http://img2.58codes.com/2024/20143762OcyoSokaTI.jpg

最后会变成:
http://img2.58codes.com/2024/201437629FwYHVaP3a.jpg

3. console.log(a.y);

因为变数a的值是adress02,adress02里面的属性只有x,无y,所以为undifined。

4. console.log(b);

变数b的值是adress01,adress01里面的属性有x且值是1,y的值里面含另一个物件,里面有属性x且值是2。


例子3:

        var a = { x: 1 };        var b = a;        a.x = { x: 2 };        a.y = a = { y: 1 };        console.log(a);  //{y: 1}        console.log(b);  //{x: {x: 2}, y: {y: 1}}

简单拆解:

        var a = { x: 1 };        var b = a;

http://img2.58codes.com/2024/20143762ZvgXZjVwHj.jpg


        a.x = { x: 2 };

http://img2.58codes.com/2024/201437622l9xoYdzY8.jpg


       a.y = a = { y: 1 };

http://img2.58codes.com/2024/20143762Ykytt5WLk9.jpg
http://img2.58codes.com/2024/20143762sgP6NbbPUc.jpg
最后变成:
http://img2.58codes.com/2024/20143762CE8WEEcWHU.jpg

最后就是连连看。

参考文章:

JavaScript’s Memory Model:https://medium.com/@ethannam/javascripts-memory-model-7c972cd2c239JavaScript's Memory Management Explained:https://blog.openreplay.com/javascript-s-memory-management-explainedVisualizing memory management in V8 Engine (JavaScript, NodeJS, Deno, WebAssembly):https://deepu.tech/memory-management-in-v8/六角学院:JavaScript 必修篇 - 前端修练全攻略:https://www.hexschool.com/courses/js-plus.html

关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章