1. 程式人生 > >JavaScript資料型別及深拷貝與淺拷貝

JavaScript資料型別及深拷貝與淺拷貝

JavaScript的資料型別分為基本型別引用型別

基本型別

基本型別包括undefined、null、string、number、boolean、(ES6中還有Symbol)

這些型別是存放在棧中的,資料大小確定,可按值訪問,直接操作儲存在變數中的實際值。

var a = 10;
var b = a;
b = 20;
console.log(a); // 10
console.log(b); // 20

複製時棧記憶體會開闢一個新記憶體來存放。按值傳遞,改變其中一個不會改變另一個,互相獨立。

引用型別

引用型別就是Object(包括Array、RegExp、Date、function)

引用型別是存放在堆記憶體中的物件。
變數是儲存在棧記憶體中的一個指標,這個指標儲存的是堆記憶體中的引用地址,指向堆記憶體中的物件。

var obj1 = new Object();
var obj2 = obj1;
obj2.name = "名字";
console.log(obj1.name);  //名字

按址傳遞,=只是將這個堆記憶體物件在棧記憶體中的地址複製了一份給obj2,但是它們指向了同一個堆記憶體物件,修改其中一個變數就是在修改另一個。

判斷資料型別的方法

typeof
typeof可以得到以下幾種型別:
number、string、boolean、object、function、undefined、symbol

typeof ''; // string 有效
typeof 1; // number 有效
typeof Symbol(); // symbol 有效
typeof true; //boolean 有效
typeof undefined; //undefined 有效
typeof null; //object 無效
typeof [] ; //object 無效
typeof new Function(); // function 有效
typeof new Date(); //object 無效
typeof new RegExp(); //object 無效

需要注意的是

typeof null; //object

而且除了function外無法具體區分其他的object

instanceof
用來判斷A是否是B的例項,返回的是一個布林值。

console.log([] instanceof Array);  //true
console.log([] instanceof Object);  //true
console.log(/^$/ instanceof RegExp);  //true

需要注意的是
這種方式判斷一個數組是否為陣列或物件的結果都為true,所以可以用Array.isArray()來判斷Array型別。
這種方式不可以用來檢測基本型別

console.log(1 instanceof Number);  //false

constructor
物件的constructor是指向其建構函式的。

console.log([].constructor === Array);  //true
console.log([].constructor === Object);  //false
console.log({}.constructor === Object);  //true
console.log([].constructor === Object);  //false
console.log(1.constructor === Number);  //true

需要注意的是
null和undefined是沒有constructor的,不能用這種方式判斷。

toString()
這種方法是最萬能的。
toString()是Object的原型方法,會返回當前物件的資料型別。通過call()使這個方法中的this指向需要檢測的值。返回的格式為[object XX]

Object.prototype.toString.call('') ;   // [object String]
Object.prototype.toString.call(1) ;    // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(Symbol()); //[object Symbol]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]
Object.prototype.toString.call(document) ; // [object HTMLDocument]
Object.prototype.toString.call(window) ; //[object global] window 是全域性物件 global 的引用

需要注意的是
toString()方法在每種類原型中都有,但是除了Object的原型,其他的都是把資料轉換為字串的意思。

淺拷貝

淺拷貝就是隻複製指向某個物件的指標,而不復制物件本身,新舊物件共享同一塊記憶體。

淺拷貝的實現方法

直接賦值

 let a = 1;
 let b = a;
 b = 2;
 console.log(a);  //2
 console.log(b);  //2

Object.assign()

 let obj = {name:'Carol', age:{child:12}}
 let copy = Object.assign({},obj);
 copy.name = 'Lee';
 copy.age.child = 24;
 console.log(obj);// {name:'Lee',age:{child:24}}

函式實現

 function shallowClone (source){
     if(!source || typeof source != 'object'){
         throw new Error ('error');
     }
     var targetObj = source.constructor === Array ? [] : {};
     for(var keys in source) {
         if(source.hasOwnProperty(keys)){
             targetObj[keys] = source[keys];
         }
     }
     return targetObj;
 }

深拷貝

複製並建立一個一模一樣的物件,不共享記憶體,修改新物件,舊物件保持不變。

深拷貝的實現方式

函式實現

//使用迴圈遍歷的方式實現陣列、物件的深拷貝

function deepClone(obj) {
  //判斷拷貝的要進行深拷貝的是陣列還是物件,是陣列的話進行陣列拷貝,物件的話進行物件拷貝
  var objClone = Array.isArray(obj) ? [] : {};
  //進行深拷貝的不能為空,並且是物件
  if (obj && typeof obj === "object") {
    for (key in obj) {
      if (obj.hasOwnProperty(key)) {
        if (obj[key] && typeof obj[key] === "object") {
          objClone[key] = deepClone1(obj[key]);
        } else {
          objClone[key] = obj[key];
        }
      }
    }
  }
  return objClone;
}

借用JSON的parse()和stringify()方法

   //借用JSON物件的stringify把物件轉為字串,然後用parse轉成新的物件
   
    function deepClone(obj){
        let _obj = JSON.stringify(obj),
        let objClone = JSON.parse(_obj);
        return objClone;
    }    
    let a=[0,1,[2,3],4],
    let b=deepClone(a);
    a[0]=1;
    a[2][0]=1;
    console.log(a,b);

圖解

在這裡插入圖片描述