參考鏈接: https://www.jianshu.com/p/1c142ec2ca45
https://blog.csdn.net/sinat_34531165/article/details/83861997
Js中的八種數據類型
JS中有 Number , String , null , undefined , Boolean , Object , BigInt,
Symbol 八種數據類型,而JS的變量,根據指向數據類型的不同,也分爲兩種類型,一種基本類型,一種引用類型.
BigInt
數據類型的目的是比Number
數據類型支持的範圍更大的整數值。在對大整數執行數學運算時,以任意精度表示整數的能力尤爲重要。使用BigInt
,整數溢出將不再是問題。
此外,可以安全地使用更加準確時間戳,大整數ID等,而無需使用變通方法。 BigInt
目前是第3階段提案, 一旦添加到規範中,它就是JS 第二個數字數據類型,也將是 JS 第8種基本數據類型:
- Boolean
- Null
- Undefined
- Number
- BigInt
- String
- Symbol
- Object
typeof函數返回結果與值對應表如下:
類型 | 結果 |
---|---|
Undefined | "undefined" |
Null | "object" |
Boolean | "boolean" |
Number | "number" |
BigInt | "bigint" |
String | "string" |
Symbol (ECMAScript 2015 新增) | "symbol" |
宿主對象(由 JS 環境提供) | 取決於具體實現 |
Function 對象 (按照 ECMA-262 規範實現 [[Call]]) | "function" |
其他任何對象 | "object" |
基本類型
Number , String , null , undefined , Boolean , Symbol
基本類型的訪問是按值訪問的,即可以操作保存在變量中的實際的值。
- 值類型:在從一個變量向另一個變量賦值基本類型時,會在該變量上創建一個新值,然後再把該值複製到爲新變量分配的位置上,即基本類型在賦值操作後,兩個變量是相互不受影響的。變量的交換等於在一個新的地方按照連鎖店的規範標準(統一店面理解爲相同的變量內容)新開一個分店,這樣新開的店與其它舊店互不相關、各自運營。
- 基本類型的變量是存放在棧區的(棧區指內存裏的棧內存)
var a='sdsdd'
var b=false
棧區 | |
a | 'sdsdd' |
y | false |
var x='dsfsdf'
var y=x
x=x+'+' //"dsfsdf+"
console.log(x,y) //dsfsdf+ dsfsdf
引用類型
javascript中除了基本類型之外就是引用類型了,即爲對象。對象是屬性和方法的集合。也就是說引用類型可以擁有屬性和方法,屬性又可以包含基本類型和引用類型。
- 引用類型:在從一個變量向另一個變量賦值引用類型時,會將該變量的引用地址賦值給變量,不會重新開闢一塊新的存儲空間。即引用類型在賦值操作後,兩個變量是相互受影響的。變量的交換等同於把現有一間店的鑰匙(變量引用地址)複製一把給了另外一個老闆,此時兩個老闆同時管理一間店,兩個老闆的行爲都有可能對一間店的運營造成影響。
- 引用類型的值是同時保存在棧內存和堆內存中的對象
var obj1={a:1,b:2,c:{d:'sdsd'}}
var obj2=obj1
obj2.a=5
console.log(obj1,obj2) // {a: 5, b: 2, c: {d: "sdsd"}} {a: 5, b: 2, c: {d: "sdsd"}}
3.引用類型比較
var x={};
var y={};
console.log(x==y);//false
console.log(x===y);//false
引用類型是按引用訪問的,即就是比較兩個對象的堆內存中的地址是否相同,那很明顯,x和y在堆內存中地址是不同的。
引用類型的存儲需要內存的棧區和堆區(堆區是指內存裏的堆內存)共同完成,棧區內存保存變量標識符和指向堆內存中該對象的指針,也可以說是該對象在堆內存的地址。
棧區 | 堆區 | ||
x | 堆內存地址1 | ---------------------------> | {} |
y | 堆內存地址1 | ---------------------------> | {} |
淺拷貝
淺拷貝:複製基本類型的屬性;引用類型的屬性複製,複製棧中的變量 和 變量指向堆內存中的對象的指針,不復制堆內存中的對象。
深拷貝
深拷貝是指複製對象的所有層級,不僅僅是複製對象最外層的屬性
(1)採用遞歸去拷貝所有層級屬性
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
//判斷ojb子元素是否爲對象,如果是,遞歸複製
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是,簡單複製
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
let a=[1,2,3,4],
b=deepClone(a);
a[0]=2;
console.log(a,b);
(2) 通過JSON對象來實現深拷貝
function deepClone2(obj) {
var _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone;
}
缺點: 無法實現對對象中方法的深拷貝,會顯示爲undefined
(3)手動實現深拷貝
let obj1 = {
a: 1,
b: 2
}
let obj2 = {
a: obj1.a,
b: obj1.b
}
obj2.a = 3;
alert(obj1.a); // 1
alert(obj2.a); // 3
(4)如果對象的value是基本類型的話,也可以用Object.assign來實現深拷貝,但是要把它賦值給一個空對象
var obj = {
a: 1,
b: 2
}
var obj1 = Object.assign({}, obj); // obj賦值給一個空{}
obj1.a = 3;
console.log(obj.a);// 1
(5)使用擴展運算符實現深拷貝
// 當value是基本數據類型,比如String,Number,Boolean時,是可以使用拓展運算符進行深拷貝的
// 當value是引用類型的值,比如Object,Array,引用類型進行深拷貝也只是拷貝了引用地址,所以屬於淺拷貝
var car = {brand: "BMW", price: "380000", length: "5米"}
var car1 = { ...car, price: "500000" }
console.log(car1); // { brand: "BMW", price: "500000", length: "5米" }
console.log(car); // { brand: "BMW", price: "380000", length: "5米" }