iT邦幫忙

0

為了轉生而點技能-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

尚未有邦友留言

立即登入留言