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

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

记忆体(memory)分两区:https://ithelp.ithome.com.tw/upload/images/20211126/20143762s9LjqrAEdP.png

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

  2. Heap Memory:主要放置函式陈述式(具名函式)的function()、Reference Type。
    https://ithelp.ithome.com.tw/upload/images/20211126/20143762yZlO4ck3cy.png

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

https://ithelp.ithome.com.tw/upload/images/20211126/20143762fWQkXrG5Nm.jpg
https://ithelp.ithome.com.tw/upload/images/20211126/20143762b6T8WKORl8.jpg
https://ithelp.ithome.com.tw/upload/images/20211126/20143762ARK1VD9UPm.jpg
图片来源:V8 Memory usage(Stack & Heap)

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

       var myNumber = 23

https://ithelp.ithome.com.tw/upload/images/20211126/20143762Up2otzi0Nd.jpg

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

https://ithelp.ithome.com.tw/upload/images/20211126/20143762SzmHrBXfDP.jpg

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

https://ithelp.ithome.com.tw/upload/images/20211126/20143762Q4vY3Svbdk.jpg

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

var myArray = [];

https://ithelp.ithome.com.tw/upload/images/20211126/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

https://ithelp.ithome.com.tw/upload/images/20211126/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

https://ithelp.ithome.com.tw/upload/images/20211126/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);  //大明,小明

https://ithelp.ithome.com.tw/upload/images/20211126/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

https://ithelp.ithome.com.tw/upload/images/20211126/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;

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

最後会变成:
https://ithelp.ithome.com.tw/upload/images/20211126/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;

https://ithelp.ithome.com.tw/upload/images/20211126/20143762ZvgXZjVwHj.jpg


        a.x = { x: 2 };

https://ithelp.ithome.com.tw/upload/images/20211126/201437622l9xoYdzY8.jpg


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

https://ithelp.ithome.com.tw/upload/images/20211126/20143762Ykytt5WLk9.jpg
https://ithelp.ithome.com.tw/upload/images/20211126/20143762sgP6NbbPUc.jpg
最後变成:
https://ithelp.ithome.com.tw/upload/images/20211126/20143762CE8WEEcWHU.jpg

最後就是连连看。

参考文章:

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

<<:  C# 入门之正则表达式匹配并替换

>>:  【Vue】建立 第一个 component | 专案实作

走骇客的路让骇客无路可走

废宅看到的几个新闻重点 上级机关视察回收厂发现圾垃车满戴、系统资讯与现况不符合,经行政程序报请南调组...

伸缩自如的Flask [day4] JWT

好的,你很辛苦的写了很多API function,但是你却不希望闲杂人等没事就call一下你的API...

Web服务器扫描工具-Nikto

前几天有练习了小蜘蛛和跳过鱼 今天还是持续练习Web的工具 透过这些工具可以辅助我们更顺利进行手动测...

【杂谈】 今天就来点闲聊吧 - 铁人赛观察①

因爲本系列後续内容另有规划,虽然会在多发表几篇。 但与系列无关,今天就先来闲聊吧! 徽章出现啦~!...

伪元素(pseudo element)、伪类别(pseudo element)

伪元素 : Before 、After Before 对指定元素添加最後一个子元素 After 对指...