js中賦值、淺拷貝和深拷貝

重點:

 

一、單線程

js引擎是單線程,模擬多線程(短時間內輪流執行多個任務的片段)

步驟:

1.切分任務

2.將任務隨機排列,組成隊列

3.按順序將任務片段送進js進程

4.js線程執行任務片段

 

二、數據類型

  • 基本數據類型的特點:直接存儲在棧(stack)中的數據
  • 引用數據類型的特點:存儲的是該對象在棧中引用,真實的數據存放在堆內存裏

1.原始值是不可改變的,原因如下:

var a = 3;
var b = a;
a = 1;
console.log(a); // 1
console.log(b); // 3

var a = 3;

var b = a;

a = 1;

 

2.引用值在堆棧中的存放

引用數據類型的特點:存儲的是該對象在棧中引用,真實的數據存放在堆內存裏 

var arr1 = [1,2,3,4,5];
var arr2 = arr1;

arr1.push(5);
console.log(arr1); // [1,2,3,4,5,5]
console.log(arr2); // [1,2,3,4,5,5]

arr1 = [1,2];
console.log(arr1); // [1,2]
console.log(arr2); // [1,2,3,4,5,5]

var arr1 = [1,2,3,4,5];

var arr2 = arr1;

當arr1.push(5);時,arr2會跟着arr1一起變化

arr1 = [1,2]

arr1重新賦值,arr2不會跟着改變

 

三、賦值

賦值:只複製指向某個對象的指針,而不復制對象本身,新舊對象還是共享同一塊內存。

var obj1 = {
    a: 1,
    b: 2,
    c: [3,4,5],
    d: function() { console.log(000); }
}
var obj2 = obj1;
obj2.a = 6;
console.log(obj1); //{a: 6, b: 2, c: Array(3), d: ƒ}
console.log(obj2); //{a: 6, b: 2, c: Array(3), d: ƒ}

四、淺拷貝

淺拷貝:創建一個新對象。如果屬性是基本類型,拷貝的就是基本類型的值;如果屬性是內存地址(引用類型),拷貝的就是內存地址 ,因此如果其中一個對象改變了這個地址,就會影響到另一個對象。 

var obj1 = {
    a: 1,
    b: 2,
    c: [3,4,5],
    d: function() { console.log(000); }
}

function shallowCopy(obj1) {
    var resultObj = {};
    for (var prop in obj1) {
        if (obj1.hasOwnProperty(prop)) {
            resultObj[prop] = obj1[prop];
        }
    }
    return resultObj;
}

var obj2 = shallowCopy(obj1);
obj2.a = 6;

obj2.c[0] = 7;

console.log(obj1); //{a: 1, b: 2, c: [7,4,5], d: ƒ}
console.log(obj2); //{a: 6, b: 2, c: [7,4,5], d: ƒ}

淺拷貝方法:

1.如上的屬性複製方法

2.Object.saaign():

var obj1 = {
    a: 1,
    b: 2,
    c: [3,4,5],
    d: function() { console.log(000); }
}

var obj2 = Object.assign({}, obj1);
obj2.a = 6;
obj2.c[0] = 7; // 淺拷貝
console.log(obj1); // {a: 1, b: 2, c: [7,4,5], d: ƒ}
console.log(obj2); // {a: 6, b: 2, c: [7,4,5], d: ƒ}

obj2.c = [8,9,0]; // 
console.log(obj1); // {a: 1, b: 2, c: [7,4,5], d: ƒ}
console.log(obj2); // {a: 6, b: 2, c: [8,9,0], d: ƒ}

3.如果是數組,可使用Array.prototype.concat()和Array.prototype.slice(),這兩個方法都不修改原數組

Array.prototype.concat():

var arr1 = [1,[2,3,4],5];
var arr2 = arr1.concat();

arr2[0] = 6;
arr2[1][0] = 7;

console.log(arr1); //[1,[7,3,4],5]
console.log(arr2); //[6,[7,3,4],5]

Array.prototype.slice():

var arr1 = [1,[2,3,4],5];
var arr2 = arr1.slice();

arr2[0] = 6;
arr2[1][0] = 7;

console.log(arr1); //[1,[7,3,4],5]
console.log(arr2); //[6,[7,3,4],5]

 

五、深拷貝

 1.JSON.parse(JSON.stringify()):用JSON.stringify將對象轉成JSON字符串,再用JSON.parse()把字符串解析成對象,一去一來,新的對象產生了,而且對象會開闢新的棧,實現深拷貝。                               

可以實現數組或對象深拷貝,但不能處理函數    

var obj1 = {
    a: 1,
    b: 2,
    c: [3,4,5],
    d: function() { console.log(000); }
}
var obj2 = JSON.parse(JSON.stringify(obj1));
console.lpg(obj2); // {a: 1, b: 2, c:[3,4,5]} //d中的函數直接被略去

2.手寫遞歸方法:遞歸方法實現深度克隆原理:遍歷對象、數組直到裏邊都是基本數據類型,然後再去複製,就是深度拷貝

//定義檢測數據類型的功能函數
    function checkedType(target) {
      return Object.prototype.toString.call(target).slice(8, -1)
    }
    //實現深度克隆---對象/數組
    function clone(target) {
      //判斷拷貝的數據類型
      //初始化變量result 成爲最終克隆的數據
      let result, targetType = checkedType(target)
      if (targetType === 'Object') {
        result = {}
      } else if (targetType === 'Array') {
        result = []
      } else {
        return target
      }
      //遍歷目標數據
      for (let i in target) {
        //獲取遍歷數據結構的每一項值。
        let value = target[i]
        //判斷目標結構裏的每一值是否存在對象/數組
        if (checkedType(value) === 'Object' ||
          checkedType(value) === 'Array') { //對象/數組裏嵌套了對象/數組
          //繼續遍歷獲取到value值
          result[i] = clone(value)
        } else { //獲取到value值是基本的數據類型或者是函數。
          result[i] = value;
        }
      }
      return result
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章