精华内容
下载资源
问答
  • JavaScript之实现深拷贝的方法 1.用递归的方式实现深拷贝 //使用递归的方式实现数组、对象的深拷贝 function deepClone(obj) { //判断拷贝的要进行深拷贝的是数组还是对象,是数组的话进行数组拷贝,对象的话...

    JavaScript之实现深拷贝的方法

    1.用递归的方式实现深拷贝

    //使用递归的方式实现数组、对象的深拷贝
    			function deepClone(obj) {
    			  //判断拷贝的要进行深拷贝的是数组还是对象,是数组的话进行数组拷贝,对象的话进行对象拷贝
    			  var objClone = Array.isArray(obj) ? [] : {};
    			  //进行深拷贝的不能为空,并且是对象或者是
    			  if (obj && typeof obj === "object") {
    			    for (key in obj) {
    			      if (obj.hasOwnProperty(key)) {
    					    //判断obj子元素是否为对象,如果是,递归复制
    			        if (obj[key] && typeof obj[key] === "object") {
    			          objClone[key] = deepClone(obj[key]);
    			        } else {
    						//不是进行简单复制
    			          objClone[key] = obj[key];
    			        }
    			      }
    			    }
    			  }
    			  return objClone;
    			}
    			var a=[1,2,3,4,5],
    			    b=deepClone(a);
    			a[0]=2;
    			console.log(a,b);
    

    在这里插入图片描述

    2.用 JSON 对象实现深拷贝

    运用JSON中的stringifyparse方法实现

    function deepClone(obj){
    			    let _obj = JSON.stringify(obj),
    			        objClone = JSON.parse(_obj);
    			    return objClone
    			}    
    			let a=[0,1,3,4,5],
    			    b=deepClone(a);
    			a[0]=1;
    			console.log(a,b);
    

    在这里插入图片描述

    3.jQuery的extend方法实现深拷贝

    $.extend( [deep ], target, object1 ,[ objectN ] )

    deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝

    target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。

    object1 objectN可选, Object类型 第一个以及第N个被合并的对象。

    let a=[0,1,2,3,4],
     b=$.extend(true,[],a);
    a[0]=1;
    console.log(a,b);
    

    在这里插入图片描述
    注意:slice并不属于深拷贝,对于一级属性确实不受影响了,但是二级属性还是没能拷贝成功所以不属于深拷贝

    参考于https://www.cnblogs.com/echolun/p/7889848.html

    展开全文
  • JS实现深拷贝和浅拷贝及区别 深拷贝和浅拷贝对比 浅拷贝 优:与深拷贝相比不占用内存,不影响性能 缺:因使用的同一个地址,B值改变,A值也会随着改变 深拷贝 优:有自己独立属性、地址,不可被更改 缺:与浅...

    JS实现深拷贝和浅拷贝及区别

    深拷贝和浅拷贝对比

    • 浅拷贝

      • 优:与深拷贝相比不占用内存,不影响性能
      • 缺:因使用的同一个地址,B值改变,A值也会随着改变
    • 深拷贝

      • 优:有自己独立属性、地址,不可被更改
      • 缺:与浅拷贝相比占用内存,并非常影响性能问题,不建议大范围的使用

    简单数组实现深拷贝方法

    • 通过for循环遍历赋值
    • arr.slice(),截取数组元素(start, end) 默认截取全部元素,不会改变原来的数组
    • arr.concat() 方法用于连接两个或多个数组,不改变原来的数组
    • […arra] 使用拓展运算符

    简单对象实现深拷贝方法

    • 通过for循环遍历赋值

    • Object.assign({}, obj):当object只有一层的时候,是深拷贝;多层时,改变多层内的数据时是浅拷贝

    • JSON.parse(JSON.stringify(obj)) 单层&多层都可以,有函数时不行

    • {…obj} 使用拓展运算符

    复杂解构的深拷贝两种写法

    第一种写法:
    function copyFn(obj) {
        if (obj == null) { return null }
        var result = Array.isArray(obj) ? [] : {};
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                if (typeof obj[key] === 'object') {
                    result[key] = copyFn(obj[key]); // 如果是对象/数组,再次调用该方法自身 
                } else {
                    result[key] = obj[key];
                }
            }
        }
        return result;
    }
    /// 测试
    // 测试对象
    var obj = {
        "a": 1, "b": [2, 3], "c": { "d": 4, "e": 5 }, "f": function (g) {
            return g * 2
        }
    }
    let obj1 = copyFn(obj)
    obj1.c.d = 0
    console.log(obj);
    console.log(obj1);
    
    // 测试数组
    var arra = [1, 2, 3, { "a": 9, "b": 8, "c": [4, 5], "d": function (g){
        return g * 2
    }}]
    let arrb = copyFn(arra)
    arrb[0] = 0
    arrb[3].a = 6
    arrb[3].c[0] = 7
    console.log(arra);
    console.log(arrb);
    
    第二种写法:
    function clone(obj) {
        var o;
        // 如果是对象object的话, 因为null,object,array也是'object';
        if (typeof obj === 'object') {
            // 如果是空的话
            if (obj === null) {
                o = null;
            } else if (obj instanceof Array) {
                // 如果是数组arr的话
                o = [];
                for (var i = 0, len = obj.length; i < len; i++) {
                    o.push(clone(obj[i]));
                }
            } else {
                // 如果是对象object的话
                o = {};
                for (var j in obj) {
                    o[j] = clone(obj[j]);
                }
            }
        }
        else {
            o = obj;
        }
        return o;
    };
    /// 测试
    // 测试数组
    var arrc = [1, 2, 3, {
        "a": 9, "b": 8, "c": [4, 5], "d": function (g) {
            return g * 2
        }
    }]
    let arrd = clone(arrc)
    arrd[0] = 0
    arrd[3].a = 6
    arrd[3].c[0] = 7
    console.log(arrc);
    console.log(arrd);
    
    // 测试对象
    var obj1 = {
        "a": 1, "b": [2, 3], "c": { "d": 4, "e": 5 }, "f": function (g) {
            return g * 2
        }
    }
    let obj2 = clone(obj1)
    obj2.c.d = 0
    console.log(obj);
    console.log(obj2);
    
    展开全文
  • 其实深拷贝可以拆分成 2 步,浅拷贝 + 递归,浅拷贝时判断属性值是否是对象,如果是对象就进行递归操作,两个一结合就实现深拷贝。 根据上篇文章内容,我们可以写出简单浅拷贝代码如下。 //木易杨 ...

    转载于:元光木易杨 前端大全 20190228

    如何实现一个深拷贝

    第一步:简单实现

    其实深拷贝可以拆分成 2 步,浅拷贝 + 递归,浅拷贝时判断属性值是否是对象,如果是对象就进行递归操作,两个一结合就实现了深拷贝。

    根据上篇文章内容,我们可以写出简单浅拷贝代码如下。

    // 木易杨
    function cloneShallow(source) {
        var target = {};
        for (var key in source) {
            if (Object.prototype.hasOwnProperty.call(source, key)) {
                target[key] = source[key];
            }
        }
        return target;
    }
    
    // 测试用例
    var a = {
        name: "muyiy",
        book: {
            title: "You Don't Know JS",
            price: "45"
        },
        a1: undefined,
        a2: null,
        a3: 123
    }
    var b = cloneShallow(a);
    
    a.name = "高级前端进阶";
    a.book.price = "55";
    
    console.log(b);
    // { 
    //   name: 'muyiy', 
    //   book: { title: 'You Don\'t Know JS', price: '55' },
    //   a1: undefined,
    //   a2: null,
    //   a3: 123
    // }
    

    上面代码是浅拷贝实现,只要稍微改动下,加上是否是对象的判断并在相应的位置使用递归就可以实现简单深拷贝。

    // 木易杨
    function cloneDeep1(source) {
        var target = {};
        for(var key in source) {
            if (Object.prototype.hasOwnProperty.call(source, key)) {
                if (typeof source[key] === 'object') {
                    target[key] = cloneDeep1(source[key]); // 注意这里
                } else {
                    target[key] = source[key];
                }
            }
        }
        return target;
    }
    
    // 使用上面测试用例测试一下
    var b = cloneDeep1(a);
    console.log(b);
    // { 
    //   name: 'muyiy', 
    //   book: { title: 'You Don\'t Know JS', price: '45' }, 
    //   a1: undefined,
    //   a2: {},
    //   a3: 123
    // }
    

    一个简单的深拷贝就完成了,但是这个实现还存在很多问题。

    • 1、没有对传入参数进行校验,传入 null 时应该返回 null 而不是 {}

    • 2、对于对象的判断逻辑不严谨,因为 typeof null === 'object'

    • 3、没有考虑数组的兼容

    第二步:拷贝数组

    我们来看下对于对象的判断,之前在【进阶3-3期】有过介绍,判断方案如下。

    // 木易杨
    function isObject(obj) {
        return Object.prototype.toString.call(obj) === '[object Object]';
    }
    

    但是用在这里并不合适,因为我们要保留数组这种情况,所以这里使用 typeof 来处理。

    // 木易杨
    typeof null //"object"
    typeof {} //"object"
    typeof [] //"object"
    typeof function foo(){} //"function" (特殊情况)
    

    改动过后的 isObject 判断逻辑如下。

    // 木易杨
    function isObject(obj) {
        return typeof obj === 'object' && obj != null;
    }
    

    所以兼容数组的写法如下。

    // 木易杨
    function cloneDeep2(source) {
    
        if (!isObject(source)) return source; // 非对象返回自身
    
        var target = Array.isArray(source) ? [] : {};
        for(var key in source) {
            if (Object.prototype.hasOwnProperty.call(source, key)) {
                if (isObject(source[key])) {
                    target[key] = cloneDeep2(source[key]); // 注意这里
                } else {
                    target[key] = source[key];
                }
            }
        }
        return target;
    }
    
    // 使用上面测试用例测试一下
    var b = cloneDeep2(a);
    console.log(b);
    // { 
    //   name: 'muyiy', 
    //   book: { title: 'You Don\'t Know JS', price: '45' },
    //   a1: undefined,
    //   a2: null,
    //   a3: 123
    // }
    

    第三步:循环引用

    我们知道 JSON 无法深拷贝循环引用,遇到这种情况会抛出异常。

    // 木易杨
    // 此处 a 是文章开始的测试用例
    a.circleRef = a;
    
    JSON.parse(JSON.stringify(a));
    // TypeError: Converting circular structure to JSON
    

    1、使用哈希表

    解决方案很简单,其实就是循环检测,我们设置一个数组或者哈希表存储已拷贝过的对象,当检测到当前对象已存在于哈希表中时,取出该值并返回即可。

    // 木易杨
    function cloneDeep3(source, hash = new WeakMap()) {
    
        if (!isObject(source)) return source; 
        if (hash.has(source)) return hash.get(source); // 新增代码,查哈希表
    
        var target = Array.isArray(source) ? [] : {};
        hash.set(source, target); // 新增代码,哈希表设值
    
        for(var key in source) {
            if (Object.prototype.hasOwnProperty.call(source, key)) {
                if (isObject(source[key])) {
                    target[key] = cloneDeep3(source[key], hash); // 新增代码,传入哈希表
                } else {
                    target[key] = source[key];
                }
            }
        }
        return target;
    }
    

    测试一下,看看效果如何。

    // 木易杨
    // 此处 a 是文章开始的测试用例
    a.circleRef = a;
    
    var b = cloneDeep3(a);
    console.log(b);
    // {
    //     name: "muyiy",
    //     a1: undefined,
    //    a2: null,
    //     a3: 123,
    //     book: {title: "You Don't Know JS", price: "45"},
    //     circleRef: {name: "muyiy", book: {…}, a1: undefined, a2: null, a3: 123, …}
    // }
    

    完美!

    2、使用数组

    这里使用了ES6 中的 WeakMap 来处理,那在 ES5 下应该如何处理呢?

    也很简单,使用数组来处理就好啦,代码如下。

    // 木易杨
    function cloneDeep3(source, uniqueList) {
    
        if (!isObject(source)) return source; 
        if (!uniqueList) uniqueList = []; // 新增代码,初始化数组
    
        var target = Array.isArray(source) ? [] : {};
    
        // ============= 新增代码
        // 数据已经存在,返回保存的数据
        var uniqueData = find(uniqueList, source);
        if (uniqueData) {
            return uniqueData.target;
        };
    
        // 数据不存在,保存源数据,以及对应的引用
        uniqueList.push({
            source: source,
            target: target
        });
        // =============
    
        for(var key in source) {
            if (Object.prototype.hasOwnProperty.call(source, key)) {
                if (isObject(source[key])) {
                    target[key] = cloneDeep3(source[key], uniqueList); // 新增代码,传入数组
                } else {
                    target[key] = source[key];
                }
            }
        }
        return target;
    }
    
    // 新增方法,用于查找
    function find(arr, item) {
        for(var i = 0; i < arr.length; i++) {
            if (arr[i].source === item) {
                return arr[i];
            }
        }
        return null;
    }
    
    // 用上面测试用例已测试通过
    

    现在已经很完美的解决了循环引用这种情况,那其实还是一种情况是引用丢失,我们看下面的例子。

    // 木易杨
    var obj1 = {};
    var obj2 = {a: obj1, b: obj1};
    
    obj2.a === obj2.b; 
    // true
    
    var obj3 = cloneDeep2(obj2);
    obj3.a === obj3.b; 
    // false
    

    引用丢失在某些情况下是有问题的,比如上面的对象 obj2,obj2 的键值 a 和 b 同时引用了同一个对象 obj1,使用 cloneDeep2 进行深拷贝后就丢失了引用关系变成了两个不同的对象,那如何处理呢。

    其实你有没有发现,我们的 cloneDeep3 已经解决了这个问题,因为只要存储已拷贝过的对象就可以了。

    // 木易杨
    var obj3 = cloneDeep3(obj2);
    obj3.a === obj3.b; 
    // true
    

    完美!

    第四步:拷贝 Symbol

    这个时候可能要搞事情了,那我们能不能拷贝 Symol 类型呢?

    当然可以,不过 Symbol 在 ES6 下才有,我们需要一些方法来检测出 Symble 类型。

    方法一:Object.getOwnPropertySymbols(...)

    方法二:Reflect.ownKeys(...)

    对于方法一可以查找一个给定对象的符号属性时返回一个 ?symbol 类型的数组。注意,每个初始化的对象都是没有自己的 symbol 属性的,因此这个数组可能为空,除非你已经在对象上设置了 symbol 属性。(来自MDN)

    var obj = {};
    var a = Symbol("a"); // 创建新的symbol类型
    var b = Symbol.for("b"); // 从全局的symbol注册?表设置和取得symbol
    
    obj[a] = "localSymbol";
    obj[b] = "globalSymbol";
    
    var objectSymbols = Object.getOwnPropertySymbols(obj);
    
    console.log(objectSymbols.length); // 2
    console.log(objectSymbols)         // [Symbol(a), Symbol(b)]
    console.log(objectSymbols[0])      // Symbol(a)
    

    对于方法二返回一个由目标对象自身的属性键组成的数组。它的返回值等同于Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))。(来自MDN)

    Reflect.ownKeys({z: 3, y: 2, x: 1}); // [ "z", "y", "x" ]
    Reflect.ownKeys([]); // ["length"]
    
    var sym = Symbol.for("comet");
    var sym2 = Symbol.for("meteor");
    var obj = {[sym]: 0, "str": 0, "773": 0, "0": 0,
               [sym2]: 0, "-1": 0, "8": 0, "second str": 0};
    Reflect.ownKeys(obj);
    // [ "0", "8", "773", "str", "-1", "second str", Symbol(comet), Symbol(meteor) ]
    // 注意顺序
    // Indexes in numeric order, 
    // strings in insertion order, 
    // symbols in insertion order
    

    方法一

    思路就是先查找有没有 Symbol 属性,如果查找到则先遍历处理 Symbol 情况,然后再处理正常情况,多出来的逻辑就是下面的新增代码。

    // 木易杨
    function cloneDeep4(source, hash = new WeakMap()) {
    
        if (!isObject(source)) return source; 
        if (hash.has(source)) return hash.get(source); 
    
        let target = Array.isArray(source) ? [] : {};
        hash.set(source, target);
    
        // ============= 新增代码
        let symKeys = Object.getOwnPropertySymbols(source); // 查找
        if (symKeys.length) { // 查找成功    
            symKeys.forEach(symKey => {
                if (isObject(source[symKey])) {
                    target[symKey] = cloneDeep4(source[symKey], hash); 
                } else {
                    target[symKey] = source[symKey];
                }    
            });
        }
        // =============
    
        for(let key in source) {
            if (Object.prototype.hasOwnProperty.call(source, key)) {
                if (isObject(source[key])) {
                    target[key] = cloneDeep4(source[key], hash); 
                } else {
                    target[key] = source[key];
                }
            }
        }
        return target;
    }
    

    测试下效果

    // 木易杨
    // 此处 a 是文章开始的测试用例
    var sym1 = Symbol("a"); // 创建新的symbol类型
    var sym2 = Symbol.for("b"); // 从全局的symbol注册?表设置和取得symbol
    
    a[sym1] = "localSymbol";
    a[sym2] = "globalSymbol";
    
    var b = cloneDeep4(a);
    console.log(b);
    // {
    //     name: "muyiy",
    //     a1: undefined,
    //    a2: null,
    //     a3: 123,
    //     book: {title: "You Don't Know JS", price: "45"},
    //     circleRef: {name: "muyiy", book: {…}, a1: undefined, a2: null, a3: 123, …},
    //  [Symbol(a)]: 'localSymbol',
    //  [Symbol(b)]: 'globalSymbol'
    // }
    

    完美!

    方法二

    // 木易杨
    function cloneDeep4(source, hash = new WeakMap()) {
    
        if (!isObject(source)) return source; 
        if (hash.has(source)) return hash.get(source); 
    
        let target = Array.isArray(source) ? [...source] : { ...source }; // 改动 1
        hash.set(source, target);
    
          Reflect.ownKeys(target).forEach(key => { // 改动 2
            if (isObject(source[key])) {
                target[key] = cloneDeep4(source[key], hash); 
            } else {
                target[key] = source[key];
            }  
          });
        return target;
    }
    
    // 测试已通过
    

    这里说一下改动 1,因为使用 Reflect.ownKeys() 获取所有的键值,所以 target 需要改成如上所示,返回一个新数组或者新对象,获取到源对象之后就可以如改动 2 所示遍历赋值即可。

    这种方式的问题在于不能深拷贝原型链上的数据,因为 Reflect.ownKeys() 返回的是目标对象自身的属性键组成的数组。如果想深拷贝原型链上的数据怎么办,那用 for..in 就可以了。

    完美!

    我们延伸下介绍以下两个知识点,分别是构造字面量数组时使用展开语法构造字面量对象时使用展开语法。(以下代码示例来源于 MDN)

    1、展开语法之字面量数组

    这是 ES2015 (ES6) 才有的语法,可以通过字面量方式, 构造新数组,而不再需要组合使用  pushspliceconcat 等方法。

    var parts = ['shoulders', 'knees']; 
    var lyrics = ['head', ...parts, 'and', 'toes']; 
    // ["head", "shoulders", "knees", "and", "toes"]
    

    这里的使用方法和参数列表的展开有点类似。

    function myFunction(v, w, x, y, z) { }
    var args = [0, 1];
    myFunction(-1, ...args, 2, ...[3]);
    

    返回的是新数组,对新数组修改之后不会影响到旧数组,类似于 arr.slice()

    var arr = [1, 2, 3];
    var arr2 = [...arr]; // like arr.slice()
    arr2.push(4); 
    
    // arr2 此时变成 [1, 2, 3, 4]
    // arr 不受影响
    

    展开语法和 Object.assign() 行为一致, 执行的都是浅拷贝(即只遍历一层)。

    var a = [[1], [2], [3]];
    var b = [...a];
    b.shift().shift(); // 1
    // [[], [2], [3]]
    

    这里 a 是多层数组,b 只拷贝了第一层,对于第二层依旧和 a 持有同一个地址,所以对 b 的修改会影响到 a。

    2、展开语法之字面量对象

    这是 ES2018 才有的语法,将已有对象的所有可枚举属性拷贝到新构造的对象中,类似于  Object.assign() 方法。

    var obj1 = { foo: 'bar', x: 42 };
    var obj2 = { foo: 'baz', y: 13 };
    
    var clonedObj = { ...obj1 };
    // { foo: "bar", x: 42 }
    
    var mergedObj = { ...obj1, ...obj2 };
    // { foo: "baz", x: 42, y: 13 }
    

    Object.assign() 函数会触发 setters,而展开语法不会。有时候不能替换或者模拟 Object.assign() 函数,因为会得到意想不到的结果,如下所示。

    var obj1 = { foo: 'bar', x: 42 };
    var obj2 = { foo: 'baz', y: 13 };
    const merge = ( ...objects ) => ( { ...objects } );
    
    var mergedObj = merge ( obj1, obj2);
    // { 0: { foo: 'bar', x: 42 }, 1: { foo: 'baz', y: 13 } }
    
    var mergedObj = merge ( {}, obj1, obj2);
    // { 0: {}, 1: { foo: 'bar', x: 42 }, 2: { foo: 'baz', y: 13 } }
    

    这里实际上是将多个解构变为剩余参数( rest ),然后再将剩余参数展开为字面量对象.

    第五步:破解递归爆栈

    上面四步使用的都是递归方法,但是有一个问题在于会爆栈,错误提示如下。

    // RangeError: Maximum call stack size exceeded
    

    那应该如何解决呢?其实我们使用循环就可以了,代码如下。

    function cloneDeep5(x) {
        const root = {};
    
        // 栈
        const loopList = [
            {
                parent: root,
                key: undefined,
                data: x,
            }
        ];
    
        while(loopList.length) {
            // 深度优先
            const node = loopList.pop();
            const parent = node.parent;
            const key = node.key;
            const data = node.data;
    
            // 初始化赋值目标,key为undefined则拷贝到父元素,否则拷贝到子元素
            let res = parent;
            if (typeof key !== 'undefined') {
                res = parent[key] = {};
            }
    
            for(let k in data) {
                if (data.hasOwnProperty(k)) {
                    if (typeof data[k] === 'object') {
                        // 下一次循环
                        loopList.push({
                            parent: res,
                            key: k,
                            data: data[k],
                        });
                    } else {
                        res[k] = data[k];
                    }
                }
            }
        }
    
        return root;
    }
    展开全文
  • js 如何实现深拷贝

    2021-01-04 16:43:33
    当数组或者对象中每一项的值都是基本数据类型时,可以通过简单的方法实现深拷贝, 数组: array.slice() array.concat es6 …解构 对象:object.assign() es6 …解构 但是当为多层嵌套的数组或者对象时,以上的方法...

    当数组或者对象中每一项的值都是基本数据类型时,可以通过简单的方法实现深拷贝,
    数组: array.slice() array.concat es6 …解构
    对象:object.assign() es6 …解构

    但是当为多层嵌套的数组或者对象时,以上的方法均会失效了

    简单的大招至上,可以通过json.stringly json.parse 进行简单粗暴的深拷贝
    还可以手写递归进行深拷贝

    const deepClone = (data) => {
    if (typeof data !== "object") return;
    const new_data = Array.isArray(data) ? [] : {};
    for (let i in data) {
    new_data[i] = typeof data[i] === "object" ? deepClone(data[i]) : data[i];
    }
    return new_data;
    };
    

    还可以引用lodash中的方法,_cloneDeep() 进行深拷贝

    展开全文
  • 我们在工作之中,前端伙伴讨论到了解构赋值到底是浅拷贝还是深拷贝,今天梳理一下。 1、ES6的解构赋值,大家应该都清楚,就是可以快速取出数组或者对象中的值; 具体使用情况如下: const a = { name: 'name'...
  • 其实深拷贝可以拆分成 2 步,浅拷贝 + 递归,浅拷贝时判断属性值是否是对象,如果是对象就进行递归操作,两个一结合就实现深拷贝。 根据上篇文章内容,我们可以写出简单浅拷贝代码如下。 // 木易杨 .
  • 其实深拷贝可以拆分成 2 步,浅拷贝 + 递归,浅拷贝时判断属性值是否是对象,如果是对象就进行递归操作,两个一结合就实现深拷贝。 根据上篇文章内容,我们可以写出简单浅拷贝代码如下。 // 木易杨 function ...
  • 浅拷贝与深拷贝 参考: 掘金文章 JS类型及存储 深拷贝和浅拷贝的主要区别就是其在内存中的存储类型不同: JS的五大基础类型 (undefined,boolean,number,string,null)都是存储在栈内存中,按值存放不可修改,...
  • ① 赋值运算 *② 扩展运算符 … ③ Object.assign( target, …sources) target参数: 代表目标对象,assign方法会改变目标对象,所以一般target会设置一个空值 …sources参数: 代表原对象...④ concat、 解构赋值等
  • 拷贝只复制对象的指针,即存在栈中的地址,新旧对象还是共用一块内存,修改任意一个对象两个对象都会改变。 //浅拷贝方法 //1.把一个对象赋值给一个变量 var obj = { name: 'zhangsan' } var obj1 = obj obj1....
  • js实现对象深拷贝

    2021-06-21 10:13:18
    目录 一、利用for(..in) 二、利用Object.assign 三、利用解构赋值 一、利用for(..in) 缺点:复杂 优点:能实现多层的深拷贝 二、利用Object.assign 缺点:只能深拷贝对象的第一层,如果对象中的属性也是对象的话,...
  • 深拷贝 function deepCopy(data) { if (typeof data !== 'object') { return data } else { var tempData = Array.isArray(data) ? [] : {} for (var i in data) { if (typeof data[i] !== 'ob...
  • 其他的,例如布尔值、数字等基础数据类型都是深拷贝(值引用)。 深拷贝 JSON.parse(JSON.stringify(src)):这种方法有局限性,如果属性值是函数或者一个类的实例的时候,无法正确拷贝 借助第三方库:jq 的extend...
  • 对象深拷贝的五种方法 1.json暴力转化 通过JSON.stringify() 和 JSON.parse() 将对象转为字符串之后在转为对象。 var obj = {name:'123'} var obj2 = JSON.parse(JSON.stringify(obj 这种简单粗暴的方式有局限性,...
  • 深拷贝,复制并创建一个一摸一样的对象(拷贝的值是一样的,但是内存地址不一样,) 1.列表内容会创建一个新的内存空间, 2.不共享内存,修改新对象,旧对象保持不变 浅拷贝 var obj={a:1,b:2,c:3}; var newObj=...
  • 深拷贝则是既赋值本身也赋值内容, js中对于引用类型的数据,默认都是浅拷贝 一、浅拷贝 (1) Object.assign() object.assign我们经常会用到合并对象,当然利用object.assign性质我们也可以实现对象的拷贝 var ...
  • 1.使用JSON暴力转换 var obj = {name:'123'}; var obj2 = JSON.parse(JSON.stringify(obj)) ...//只能深度拷贝对象的第一层,如果对象中的属性也是对象的话,没有办法进行深度拷贝 3. 利用循环和递归的方式 funct
  • 上面一段代码在react中很常见,进行对象解构赋值后的...由于返回的是一个{ },所以返回的也是一个深拷贝后的对象。 进一步扩展 在React的store中的对象里,会存在很多个key、value,那么,当我们修改其中一个值并返...
  • 今天这篇文章我们来看看一道必会面试题,即如何实现一个深拷贝。本文会详细介绍对象、数组、循环引用、引用丢失、Symbol 和递归爆栈等情况下的深拷贝实践,欢迎阅读。 第一步:简单实现 其实深拷贝可以拆分成 2 步,...
  • 废话不多说直接上代码,新建一个对象。 let obj = { a: { A: { end: true }, B: 2, C: 3, }, ... 深度优先遍历,先将obj转化成可迭代对象,在里面执行递归函数,将深层对象作为递归... * 对象的深拷贝也可...
  • Object.assign浅拷贝拷贝一层) var obj ={ name:'张珊', age:16, list:{a:'我我哦'} } // var o = obj ; // Object.assign 浅拷贝 拷贝一层 var o =Object.assign({},obj) ; o.list.a...
  • 1.首先要清楚,深拷贝和浅拷贝只是在引用数据类型(obj,Function,Array等)中才会有区别,基本数据类型不适用。 基本数据类型:Boolean Null Undefined Number String Symbol (ES6) BigInt (ES10) 引用数据类型:...
  • * 递归深度遍历数据结构,对数据结构进行深拷贝 * @param obj * @returns {*} */ function deepClone1(obj) { var objClone = Array.isArray(obj) ? [] : {}; if (obj && typeof obj === "object") { for (let ...
  • 这是一道经典的面试题,相信大多数同学都有被面试官问过的经历,那么你能实现几种深拷贝和浅拷贝的方法呢?是不是又问到了你的知识盲区,那让我们来一起总结常用的深浅拷贝(克隆)的方法吧!开始之前在开始之前,我们...
  • 一篇文章彻底搞懂浅拷贝和深拷贝

    万次阅读 多人点赞 2018-07-16 16:36:32
    强烈推荐30个原生JavaScript的demo,包括canvas时钟特效、自定义视频...【javascript】详解javaScript的深拷贝 目录 浅谈深拷贝和浅拷贝 深拷贝和浅拷贝的区别 为什么要使用深拷贝深拷贝的要求程度...
  • 文章目录1 数据类型2 浅拷贝与深拷贝3 实现深拷贝方法3.1 JSON.string() 结合 JSON.parse()3.2 递归4 JS 中的拷贝方法4.1 concat4.2 slice4.3 ...4.4 Object.assign5 以上方法比较6 参考文章 1 数据类型 在 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,664
精华内容 1,065
关键字:

解构实现实现深拷贝