寫在最前面:這是我即將開始寫的一個系列样勃,主要是在框架橫行的時代,雖然上班用的是框架性芬,但是對于面試峡眶,以及技術(shù)進(jìn)階,JS基礎(chǔ)知識的鋪墊是錦上添花植锉,也是不得不學(xué)習(xí)的一塊知識辫樱,雖然開汽車的不需要很懂汽車,只需要掌握汽車的常用功能即可俊庇。但是如果你懂汽車狮暑,那你也能更好地開車,同理暇赤。當(dāng)然心例,一篇文章也不會光光只講一個知識點,一般會將有關(guān)聯(lián)的知識點串聯(lián)起來鞋囊,一邊記錄自己的學(xué)習(xí)止后,一邊分享自己的學(xué)習(xí),互勉!如果可以的話译株,也請給我點個贊瓜喇,你的點贊也能讓我更加努力地更新!
概覽
- 食用時間: 6-12分鐘
- 難度: 中等歉糜,別跑乘寒,看完再走
系列目錄
-
一文搞懂JS系列(一)之編譯原理,作用域匪补,作用域鏈伞辛,變量提升,暫時性死區(qū)
-
一文搞懂JS系列(二)之JS內(nèi)存生命周期夯缺,棧內(nèi)存與堆內(nèi)存蚤氏,深淺拷貝
JS內(nèi)存生命周期
-
分配內(nèi)存
-
內(nèi)存的讀與寫
-
釋放內(nèi)存
棧內(nèi)存與堆內(nèi)存
JS數(shù)據(jù)類型
在講棧內(nèi)存與堆內(nèi)存之前,大家應(yīng)該都知道JS分為兩種數(shù)據(jù)類型:
-
基本數(shù)據(jù)類型
String , Number , Boolean , null , undefined , Symbol (大小固定踊兜,體積輕量竿滨,相對簡單)
-
引用數(shù)據(jù)類型
Object , Array , Function (大小不一定,占用空間較大捏境,相對復(fù)雜)
內(nèi)存存儲機(jī)制
var a=true; //布爾型于游,基本數(shù)據(jù)類型
var b='jack'; //字符型,基本數(shù)據(jù)類型
var c=18; //數(shù)值型垫言,基本數(shù)據(jù)類型
var d={name:'jack'}; //對象贰剥,引用數(shù)據(jù)類型
var d=[0,1,2,3,4,5]; //數(shù)組,引用數(shù)據(jù)類型
正是因為數(shù)據(jù)類型的不同骏掀,所以他們的存放方式也不同鸠澈,就和現(xiàn)實生活中窮人和富人的住所完全不一樣(扯遠(yuǎn)了)。我們先來看一張圖:
可以看到, a
, b
, c
都是基本數(shù)據(jù)類型截驮, d
和 e
都是引用數(shù)據(jù)類型笑陈,他們在存放方式上有著本質(zhì)性的區(qū)別,基本數(shù)據(jù)類型的值是存放在棧內(nèi)存中的葵袭,而引用數(shù)據(jù)類型的值是存放在堆內(nèi)存中的涵妥,棧內(nèi)存中僅僅存放著它在棧內(nèi)存中的引用(即它在堆內(nèi)存中的地址),就和它的名字一樣坡锡,引用數(shù)據(jù)類型
內(nèi)存訪問機(jī)制
上面講的是存儲蓬网,接下來說一下變量的訪問,基本數(shù)據(jù)類型可以直接從棧內(nèi)存中訪問變量的值鹉勒,而引用數(shù)據(jù)類型要先從棧內(nèi)存中找到它對應(yīng)的引用地址帆锋,再拿著這個引用地址,去堆內(nèi)存中查找禽额,才能拿到變量的值
深淺拷貝
-
淺拷貝
上面已經(jīng)和大家說過了基本數(shù)據(jù)類型與引用數(shù)據(jù)類型在存儲上的不同锯厢,那么皮官,接下來說的這個深淺拷貝,想必大家也在面試題中經(jīng)常碰到实辑,老方式捺氢,先來看一段代碼
var name='jack';
var obj={
age:24
};
var nameCopy=name;
var objCopy=obj;
nameCopy='bob';
objCopy.age=15;
console.log(name); //jack
console.log(obj.age); //15
你會發(fā)現(xiàn), name
是沒有被影響的剪撬,而我們命名是修改objCopy.age
摄乒,為什么還會影響到 obj.age
呢,這就是因為深淺拷貝的問題在搗鬼残黑,先來看下下面的一張圖
之所以會出現(xiàn)這種情況馍佑,是因為JS對于基本類型和引用類型的,當(dāng)我們在復(fù)制引用類型的時候梨水,復(fù)制的是該對象的引用地址挤茄,所以,在執(zhí)行 var objCopy=obj;
的時候冰木,將 obj
的引用地址復(fù)制給了 objCopy
,所以笼恰,這兩個對象實際指向的是同一個對象踊沸,即改變 objCopy
的同時也改變了 obj
的值,我們將這種情況稱為淺拷貝社证,僅僅復(fù)制了對象的引用逼龟,并沒有開辟新的內(nèi)存,拿人手短追葡,拷貝地太淺了腺律。(只有引用類型才會出現(xiàn)淺拷貝的情況)
-
深拷貝
再來看接下來的一段代碼
var name='jack';
var obj={
age:24
};
var nameCopy=name;
var objCopy=JSON.parse(JSON.stringify(obj));
nameCopy='bob';
objCopy.age=15;
console.log(name); //jack
console.log(obj.age); //24
可以發(fā)現(xiàn),在經(jīng)過 JSON.parse(JSON.stringify(obj))
轉(zhuǎn)換了以后,淺拷貝不復(fù)存在宜肉,這一波是深拷貝匀钧,深拷貝開辟了新的堆內(nèi)存地址,并且將對象的引用指向了新開辟的內(nèi)存地址谬返,和前面復(fù)制的對象完全獨立之斯,自立根生,拷貝地很深遣铝,學(xué)功夫?qū)W到家佑刷,自立門戶的感覺。
-
另外實現(xiàn)深拷貝的方法(更多方式請自行百度)
var objCopy=Object.assign({},obj); //對象深拷貝的方法 Object.assign
var arrayCopy=array.concat(); //數(shù)組深拷貝的方法 concat() (數(shù)組無嵌套對象或者數(shù)組可用)
var arrayCopy=array.slice(); //數(shù)組深拷貝的方法 slice() (數(shù)組無嵌套對象或者數(shù)組可用)
JSON.parse(JSON.stringify(array)) //順帶提下酿炸,JSON.parse(JSON.stringify()) 數(shù)組和對象通用
接著上面的數(shù)組容易踩坑的地方 瘫絮,來看一個例子
var array = [{name: 'jack'}, ['old']];
var arrCopy = array.concat();
arrCopy[0].name='new';
console.log(array); // [{name: 'new'}, ['old']]
console.log(arrCopy); // [{name: 'new'}, ['old']]
可以清楚地看到(數(shù)組無嵌套對象或者數(shù)組可用的情況下用 concat
和 slice
才有效)