js-數據類型及淺拷貝深拷貝

參考鏈接: 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

基本類型的訪問是按值訪問的,即可以操作保存在變量中的實際的值。

  1. 值類型:在從一個變量向另一個變量賦值基本類型時,會在該變量上創建一個新值,然後再把該值複製到爲新變量分配的位置上,即基本類型在賦值操作後,兩個變量是相互不受影響的變量的交換等於在一個新的地方按照連鎖店的規範標準(統一店面理解爲相同的變量內容)新開一個分店,這樣新開的店與其它舊店互不相關、各自運營。
  2. 基本類型的變量是存放在棧區的(棧區指內存裏的棧內存)
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中除了基本類型之外就是引用類型了,即爲對象。對象是屬性和方法的集合。也就是說引用類型可以擁有屬性和方法,屬性又可以包含基本類型和引用類型。

  1. 引用類型:在從一個變量向另一個變量賦值引用類型時,會將該變量的引用地址賦值給變量,不會重新開闢一塊新的存儲空間。即引用類型在賦值操作後,兩個變量是相互受影響的變量的交換等同於把現有一間店的鑰匙(變量引用地址)複製一把給了另外一個老闆,此時兩個老闆同時管理一間店,兩個老闆的行爲都有可能對一間店的運營造成影響。
  2. 引用類型的值是同時保存在棧內存和堆內存中的對象
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米" }

 

發佈了65 篇原創文章 · 獲贊 85 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章