我們知道辞槐,JavaScript 是一門弱類型的語言壶硅,它創(chuàng)建的變量保存的值是可以在腳本生命周期內(nèi)改變的腊凶,假如初始化定義的變量值為數(shù)字(var a = 1;
)编矾,然后進行改變它的值的操作(a = a + '個';
)狼渊,這個變量值就會轉(zhuǎn)換為字符串類型(alert(a); // "1個"
)箱熬。實際上类垦,JavaScript 的變量實際復(fù)雜程度還遠不止如此。
基本類型和引用類型
一個變量可以存放兩種類型的值城须,基本類型的值(primitive values)和引用類型的值(reference values)蚤认。基本類型值指的是簡單的數(shù)據(jù)段糕伐,而引用類型值指那些可能由多個值構(gòu)成的對象砰琢。
JavaScript 中共有 6 種基本數(shù)據(jù)類型:Undefined、Null良瞧、Boolean陪汽、Number、String褥蚯、Symbol (new in ES 6) 挚冤!
基本類型的幾個特點:
1.基本類型的值是不可變的;
2.基本類型的比較是值的比較赞庶;
3.基本類型的變量是存放在棧區(qū)的(棧區(qū)指內(nèi)存里的棧內(nèi)存)训挡。
除了上面的 6 種基本數(shù)據(jù)類型外,剩下的就是引用類型了歧强,統(tǒng)稱為 Object 類型澜薄。細分的話,有:Object 類型摊册、Array 類型肤京、Date 類型、RegExp 類型茅特、Function 類型 等蟆沫。
引用類型的幾個特點:
1.引用類型的值是可變的;
2.引用類型的值是同時保存在棧內(nèi)存和堆內(nèi)存中的對象温治;
3.引用類型的比較是引用的比較饭庞。
進一步了解基本類型和引用類型,參見文末的參考文章熬荆。
對引用類型不同的拷貝方式
基于以上對 JavaScript 的兩種不同數(shù)據(jù)類型的理解舟山,我們知道,對一個保存了基本類型值的變量和一個保存了引用類型值的變量卤恳,它們的賦值累盗、拷貝和類型檢測等操作是不一樣的,而導(dǎo)致這種差異的原因突琳,歸根結(jié)底若债,是因為它們在內(nèi)存中儲存的方式不一樣〔鹑冢基本類型的值是保存在內(nèi)存的棧區(qū)中蠢琳,引用類型的值是由內(nèi)存中的棧區(qū)和堆區(qū)共同完成保存啊终,棧區(qū)保存的是堆內(nèi)存的地址或者說指向堆內(nèi)存中的對象的指針,堆內(nèi)存中的對象才是引用類型的實際值傲须。
淺拷貝
實際上蓝牲,基本類型值的拷貝,并不涉及到淺拷貝與深拷貝泰讽,因為對它的拷貝是在內(nèi)存中新開辟一段棧內(nèi)存例衍,變量之間互不影響。引用類型值的拷貝則不一樣已卸,在棧內(nèi)存中佛玄,兩個變量都保存了同一個對象地址,則這兩個變量指向了同一個堆內(nèi)存中的對象累澡。因此翎嫡,改變其中任何一個變量,都會相互影響永乌。我們把這兩種類型的值的拷貝放在這里比較:
基本類型值的拷貝
var num1 = 5;
var num2 = num1;
引用類型值的拷貝
var obj1 = new Objuect();
var obj2 = obj1;
obj1.name = "Nicholas";
alert (obj2.name); // "Nicholas"
深拷貝
拷貝一個引用類型的值惑申,除了單純地拷貝它的引用(棧內(nèi)存地址),有沒有辦法拷貝它真實的值(堆內(nèi)存中的對象)呢翅雏?其實辦法有很多種圈驼,并且針對不同的引用類型的值也有不同的深拷貝方法,以下是常用的深拷貝方法:
第一種:for循環(huán)實現(xiàn)對象的深拷貝
//如果包含屬性值是數(shù)組望几,無法深層拷貝數(shù)組里面的數(shù)據(jù)
var obj = {
name: 'jingjing',
sex: 'girl',
old: '18'
}
var obj2 = copyObj(obj)
function copyObj(obj) {
let res = {}
for (var key in obj) {
res[key] = obj[key]
}
return res
}
第二種:轉(zhuǎn)換成json再轉(zhuǎn)換成對象實現(xiàn)對象的深拷貝(對象里面不包含函數(shù)的情況下使用,注意這種直接粗暴的方法只能拷貝json格式數(shù)據(jù)對象绩脆,函數(shù)會丟失)
var obj = {
name: jingjing',
sex: 'girl',
old: '18'
}
var obj2 = JSON.parse(JSON.stringify(obj))
第三種:擴展運算符實現(xiàn)對象的深拷貝(隨著es6的逐漸推廣,此招兒推薦使用)
//如果包含的屬性值是數(shù)組橄抹,無法深層拷貝數(shù)組里面的數(shù)據(jù)
var obj = {
name: 'jingjing',
sex: 'girl',
old: '18'
}
var { ...obj2 } = obj
obj.old = '22'
console.log(obj) //{name: "jingjing", sex: "girl", old: "22"}
console.log(obj2) //{name: "jingjing", sex: "girl", old: "18"}
總結(jié)
在 JavaScript 中靴迫,有兩種不同的類型的變量,分別是保存了基本類型的值的變量和保存了引用類型的值的變量楼誓,這兩種類型的值因為在內(nèi)存中的儲存方式的異同玉锌,所以相應(yīng)的操作也不同。在這篇文章中疟羹,我們具體分析了引用類型中對象的拷貝方法主守,實際應(yīng)用中用到深拷貝的地方也比較多。希望這篇文章對您有用榄融,文中如有不當之處参淫,敬請指出。
參考文章:
JavaScript 深入了解基本類型和引用類型的值
本文由博客群發(fā)一文多發(fā)等運營工具平臺 OpenWrite 發(fā)布