美文网首页
JS中深度拷贝引发的一系列“惨案”

JS中深度拷贝引发的一系列“惨案”

作者: 超人有点忙 | 来源:发表于2017-12-05 16:27 被阅读0次

最近在做项目的时候遇到了JS对象地址指向的问题,需求是某个页面是通过一个对象构建出来的,但是在关闭这个窗口的时候会清空这个对象的值,导致之前赋值的新对象值也被清空了。这个时候就要用到拷贝了。
后来就得知了JSON.parse(JSON.stringify(obj或者array))这个方法可以实现深拷贝,又过了几天发现了另一个问题,我需要将两个反序列化出来的JSON对象取一个并集,然后我就百度得知了 jQuery的 $.extend 方法。后来学习了一下发现也具有拷贝的功能。下面就先理解一下$.extend这个方法。

$.extend函数理解

  1. 方法的原型
    jQuery.extend( target [, ] [, objectN ] ) 返回Object
    描述: 将两个或更多对象的内容合并到第一个对象。
target object1 objectN
一个对象,如果附加的对象被传递给这个方法将那么它将接收新的属性,如果它是唯一的参数将扩展jQuery的命名空间。如果想把结果赋给一个新的对象,并且不修改参数对象,将第一个参数设为'{}',并用一个新的对象接收返回值 一个对象,它包含额外的属性合并到第一个参数 包含额外的属性合并到第一个参数
  1. 扩展方法
    jQuery.extend( [deep ], target, object1 [, objectN ] )
deep target object1 objectN
boolean型不支持为false 如果为true 代表深拷贝 对象的扩展,接收新的属性 一个对象,包含额外属性合并到第一个参数上,如果第一个参数为空,自己就变成“第一个参数”,则会修改自己本身,然后被$.extend返回 包含额外的属性合并到第一个参数

这就是基本的两个extend用法,需要注意的地方有很多,这里就有一个小插曲。。。我在一开始没有深刻理解,用了第一种方法。
$.extend({},obj1,JSON.parse(JSON.stringify(obj2)));
我的obj1 和 obj2 都是数组,但是返回值是对象,把我的数据结构改变了,我就想办法将对象再转换成数组,方法是:

$.extend(obj1, JSON.parse(JSON.stringify(obj2)));
obj1.length = getLength(obj1);
obj1 = Array.prototype.slice.call(_obj1)
    function getLength(o) {
        var count = 0;
        for (var i in o) {
            count++;
        }
        return count;
    };

网上查到Array.prototype.slice.call这个方法可以将对象直接转换成数组,但是我一开始试了一下发现不行,因为对象没有length属性,所以我就写了一个getLength方法,专门来取对象的长度,发现果然行得通。
后来处于好奇心总觉得对这里没太搞清楚,其实是我自己改变了数据结构,就是因为第一个参数是"{}"的原因,改成"[]" 就可以了,带了“true”它不仅可以拷贝第一层级的属性,还可以一直“刨根问底”,将属性中的子类对象全部拷贝。这里引用一个API上的例子吧

//1.合并两个对象,并修改第一个对象。
var object1 = {
  apple: 0,
  banana: { weight: 52, price: 100 },
  cherry: 97
};
var object2 = {
  banana: { price: 200 },
  durian: 100
};
//Merge object2 into object1
$.extend( object1, object2 );
//结果:{"apple":0,"banana":{"price":200},"cherry":97,"durian":100}
 
//2.采用递归方式合并两个对象,并修改第一个对象。
var object1 = {
  apple: 0,
  banana: { weight: 52, price: 100 },
  cherry: 97
};
var object2 = {
  banana: { price: 200 },
  durian: 100
};
// Merge object2 into object1, recursively
$.extend( true, object1, object2 );
//结果:{"apple":0,"banana":{"weight":52,"price":200},"cherry":97,"durian":100}

相关文章

  • JS中深度拷贝引发的一系列“惨案”

    最近在做项目的时候遇到了JS对象地址指向的问题,需求是某个页面是通过一个对象构建出来的,但是在关闭这个窗口的时候会...

  • js 深度拷贝

    深拷贝(deepClone) 对于一个引用类型,如果直接将它赋值给另一个变量,由于这两个引用指向同一个地址,这时改...

  • 📎js深度拷贝

    方法1 定义方法clone 方法1缺点:无法拷贝函数 方法2 使用 JSON.stringify 和 JSON.p...

  • 手写实现深度拷贝

    手写实现深度拷贝 本文参考:面试题之如何实现一个深拷贝 基础理论 拷贝的基础是赋值,在 js 中,将一个变量赋值给...

  • JS中的深拷贝与浅拷贝

    知乎:js中的深拷贝和浅拷贝? 掘金: js 深拷贝 vs 浅拷贝 前言 首先深拷贝与浅拷贝只针对 Object,...

  • JS实现深拷贝、instanceof、判断是否为数组

    JS深拷贝 JS中拷贝对象可以按照拷贝的程度可以分为浅拷贝和深拷贝,有些时候我们需要拷贝之后的对象和拷贝之前的对象...

  • JS 小练习

    JS 小练习 数组深度拷贝 在JS中,对于对象类型的变量的引用是通过类似C之类的“指针”的方式来操作的,及如果多个...

  • 面试总结之基础篇(1)

    深拷贝与浅拷贝 原型与原型链 防抖节流 this 指向 new关键字 深度剖析js闭包

  • vue3 ts版本深度拷贝功能推荐ts-deepmerge

    在使用js版本开发vue的时候,需要用到深度拷贝。一般都是用的deepMerge这个进行深度拷贝。但是在VUE3里...

  • js深拷贝广度优先及深度优先处理Symbol

    js对象深拷贝,文章使用了广度优先和深度优先,同时也出来了symbol类型的拷贝。 文章转载优化来源:

网友评论

      本文标题:JS中深度拷贝引发的一系列“惨案”

      本文链接:https://www.haomeiwen.com/subject/mzpqixtx.html