js數據類型賦值,淺拷貝,深拷貝

直接上代碼是個人風格

一,賦值

  1. 基本數據類型的賦值
var a = 10;
    var b = a;
    b = 24;
    console.log(a); // 10 a不受b的影響。
    console.log(b) // 24
    // 基本數據類型賦值時。。是copy一份10的值。
    // 當b=24時。a不受b的影響。
複製代碼
  1. 複雜數據類型的賦值
var obj = {
        age: 12
    }
    var obj1 = obj;
    obj1.age = 18;
    console.log(obj); // {age: 18}
    console.log(obj1); // {age: 18}
    // 複雜數據類型賦值時。。是copy一份引用地址如0x1111。
    // 當obj1 = obj;時。obj和obj1引用同樣。指向同一片堆內存空間。
    // 因此當obj1.age = 18時。一樣也會更改obj2。
複製代碼

二,淺拷貝與深拷貝

注意: 淺拷貝和深拷貝都主要針對複雜數據類型

  1. 淺拷貝:淺拷貝只複製指向某個對象的指針,而不復制對象自己,新舊對象仍是共享同一塊內存。
  2. 深拷貝:但深拷貝會另外創造一個如出一轍的對象,新對象跟原對象不共享內存,修改新對象不會改到原對象。

二,淺拷貝與賦值

  1. 淺拷貝
// 直接上代碼吧
    function shallowCopy(oldObj) {
        var newObj = {};
        for(var prop in oldObj) {
            // 全部繼承了 Object 的對象都會繼承到 hasOwnProperty 方法。
            // 這個方法能夠用來檢測一個對象是否含有特定的自身屬性;若是有返回true。不然返回false
            // 和 in 運算符不一樣,該方法會忽略掉那些從原型鏈上繼承到的屬性。
            if(oldObj.hasOwnProperty(prop)){
                newObj[prop] = oldObj[prop]
            }
        }
        return newObj;
    }
    // 淺拷貝
    var obj1 = {
        a: 1, 
        b: [2,3,4], 
        c: [[5,6]] // 注意:這裏多一層引用數據類型
    }
    var obj2 = shallowCopy(obj1); 
    
    obj2.a = 18;
    obj2.b = ['二', '三', '四'];
    obj2.c[0] = ['五', '六'];
    
    console.log('obj1===',obj1) 
    console.log('obj2===',obj2) 
    
    // 若是對象只有一層。。深拷貝 和 淺拷貝同樣。
    
    
複製代碼

  1. 賦值
// 賦值
    var obj1 = {
        a: 1, 
        b: [2,3,4], 
        c: [[5,6]] // 注意:這裏多一層引用數據類型
    }
    var obj3 = obj1;
    
    obj3.a = 18;
    obj3.b = ['二', '三', '四'];
    obj3.c[0] = ['五', '六'];
    
    console.log('obj1===',obj1) 
    console.log('obj3===',obj3) 
    
    // 共享一片內存。全部值都會改變。
    
複製代碼

三,淺拷貝實現方式

  1. 本身封裝
function shallowCopy(oldObj) {
        var newObj = {};
        for(var prop in oldObj) {
            // 全部繼承了 Object 的對象都會繼承到 hasOwnProperty 方法。
            // 這個方法能夠用來檢測一個對象是否含有特定的自身屬性;若是有返回true。不然返回false
            // 和 in 運算符不一樣,該方法會忽略掉那些從原型鏈上繼承到的屬性。
            if(oldObj.hasOwnProperty(prop)){
                newObj[prop] = oldObj[prop]
            }
        }
        return newObj;
    }
複製代碼
  1. 使用Object.assign()
var pj = { a: {a: "彭彭", b: 39} };
    var pj1 = Object.assign({}, obj);
    pj1.a.a = "wade";
    console.log(pj.a.a); //wade
    
複製代碼

注意:當object只有一層的時候,是深拷貝數組

var pj = { a: {a: "彭彭", b: 39} };
    var pj1 = Object.assign({}, obj);
    pj1.a.a = "wade";
    console.log(pj.a.a); //wade
    
複製代碼
  1. 數組的淺拷貝
// 第一種
    let arr = [1, 3, {
        username: '彭彭'
    }];
    let arr2=arr.concat();    
    arr2[2].username = '君';
    
    console.log(arr[2].username); // 君
    
    // 第二種
    let arr = [1, 3, {
        username: ' 彭彭'
    }];
    let arr3 = arr.slice();
    arr3[2].username = '君';
    console.log(arr[2].username); // 君
    
    // 通常不多用到數組的拷貝。
    // 數組淺拷貝和對象是同樣的
複製代碼

原數組的元素會按照下述規則拷貝:
函數

  • 若是該元素是個對象引用(不是實際的對象),slice 會拷貝這個對象引用到新的數組裏。兩個對象引用都引用了同一個對象。若是被引用的對象發生改變,則新的和原來的數組中的這個元素也會發生改變。
  • 對於字符串、數字及布爾值來講(不是 String、Number 或者 Boolean 對象),slice 會拷貝這些值到新的數組裏。在別的數組裏修改這些字符串或數字或是布爾值,將不會影響另外一個數組。

四,深拷貝

  1. JSON.parse(JSON.stringify())
var pj = {
        name: '彭彭',
        handle: function(){} 
    };
    
    var deepPj = JSON.parse(JSON.stringify(pj)); // {name: "彭彭"}。。這種方式弊端在於沒法拷貝方法。
複製代碼
  1. 自覺手動封裝了
function deepCopy(oldObj) {
        var newObj;
        var oldObjType = Object.prototype.toString.call(oldObj).slice(8, -1);
        if(oldObjType === 'Object'){
            newObj = {};
        }else if(oldObjType === 'array'){
            newObj = [];
        }else{
            return oldObj;
        }
        
        for(let prop in oldObj){
            let value = oldObj[prop];
            let valueType = Object.prototype.toString.call(value).slice(8, -1);
            if (valueType === 'Object' || valueType = 'Array') {
                deepCopy(value);
            } else {
                newObj[prop] = value;
            }
        }
        
        return newObj;
    }
複製代碼
  1. 借用第三方庫 函數庫lodash
  • 該函數庫也有提供_.cloneDeep用來作 Deep Copy
var _ = require('lodash');
var obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f); // false
複製代碼

參考文章:juejin.im/post/5b5dcf…post

相關文章
相關標籤/搜索