资讯专栏INFORMATION COLUMN

深入JavaScript中深拷贝和浅拷贝

TalkingData / 1877人阅读

摘要:深拷贝和浅拷贝问题的本质还是不同数据类型的存储方式差异,尤其是引用数据类型的特殊。

深拷贝和浅拷贝问题的本质还是不同数据类型的存储方式差异,尤其是引用数据类型的特殊。

现分别对赋值、浅拷贝、深拷贝做深入研究:

1.赋值

原理:直接将对象指针直接赋值给另一个变量

代码

let developer = {
    title: "Frontend",
    basic: {
        html: "5",
        css: "3",
        js: "es6"
    },
    frameworks: ["React", "Vue", "AngularJS"],
    summary: function(){
        console.log("I am FE developer");
    }
};

let newDeveloper = developer;

console.log(newDeveloper);

//基本类型:改变原对象
newDeveloper.title = "Frontend Leader";
console.log(developer.title); // Frontend Leader

//对象:改变原对象
newDeveloper.basic.http = "2.0";
console.log(developer.basic.http); // 2.0
newDeveloper.basic.js = "es5";
console.log(developer.basic.js); // es5

//数组:改变原对象
newDeveloper.frameworks.push("Angular");
console.log(developer.frameworks); // [ "React", "Vue", "AngularJS", "Angular" ]

//函数:改变原对象
newDeveloper.summary = function () {
    console.log("I like FE development");
};
developer.summary(); // I like FE development
2.浅拷贝

原理:遍历对象的每个属性进行逐个拷贝

实现方式

方式1:遍历并复制

方式2:Object.assign()

代码

let developer = {
    title: "Frontend",
    basic: {
        html: "5",
        css: "3",
        js: "es6"
    },
    frameworks: ["React", "Vue", "AngularJS"],
    summary: function(){
        console.log("I am FE developer");
    }
};

/*
* 方式1:逐个复制
*
* */
function cloneInShallow(source) {
    let target = {};

    for (prop in source){
        target[prop] = source[prop];
    }

    return target
}
let newDeveloper = cloneInShallow(developer);

/*
* 方式2:Object.assign()
*
* */
// let newDeveloper = Object.assign({}, developer);

console.log(newDeveloper);

//基本类型:不改变原对象
newDeveloper.title = "Frontend Leader";
console.log(developer.title); // Frontend

// 对象:改变原对象
newDeveloper.basic.http = "2.0";
console.log(developer.basic.http); // 2.0
newDeveloper.basic.js = "es5";
console.log(developer.basic.js); // es5

//数组:改变原对象
newDeveloper.frameworks.push("Angular");
console.log(developer.frameworks); // [ "React", "Vue", "AngularJS", "Angular" ]

//函数:不改变原对象
newDeveloper.summary = function () {
    console.log("I like FE development");
};
developer.summary(); // I am FE developer
3.深拷贝

原理:使用递归,遍历每一个对象属性进行拷贝

实现方式

方式1: 纯手工打造回调函数

方式2: JSON.parse(JSON.stringify(obj))

方式3: 借助jQuery

方式4: 借助lodash

代码

let developer = {
    title: "Frontend",
    basic: {
        html: "5",
        css: "3",
        js: "es6"
    },
    frameworks: ["React", "Vue", "AngularJS", {node: "express"}],
    summary: function(){
        console.log("I am FE developer");
    }
};

/*
* 方式1: 纯手工打造
* */
function cloneInDeep(source) {
    if(source && typeof source === "object"){
        let target = {};
        for (let prop in source){
            let value = source[prop];

            if(Array.isArray(value)){
                let newArray = [];
                value.forEach(function (item, index) {
                    if(Array.isArray(item) || Object.getPrototypeOf(item) === Object.prototype){
                        newArray.push(cloneInDeep(item))
                    }else{
                        newArray.push(item)
                    }
                });

                target[prop] = newArray;
            }else if(Object.getPrototypeOf(value) === Object.prototype){
                target[prop] = cloneInDeep(value);
            }else{
                target[prop] = value;
            }
        }

        return target
    }else{
        throw new Error("source is not object!")
    }
}
let newDeveloper = cloneInDeep(developer);


/*
* 方式2: JSON.parse(JSON.stringify(obj))
* 弊端:会抛弃对象的constructor
* 适用:能够被json直接表示的数据结构,对象中只包含number、string、boolean、array、扁平对象
* 不适用:含有function、regexp
* */
// let newDeveloper = JSON.parse(JSON.stringify(developer));


/*
* 方式3: jQuery
* */
let $ = require("jquery");
// let newDeveloper = $.extend({}, developer);

/*
* 方式4: lodash
* */
let _ = require("lodash");
// let newDeveloper = _.cloneDeep(developer);


console.log(newDeveloper);

//基本类型:不改变原对象
newDeveloper.title = "Frontend Leader";
console.log(developer.title); // Frontend

// 对象:不改变原对象
newDeveloper.basic.http = "2.0";
console.log(developer.basic.http); // undefined
newDeveloper.basic.js = "es5";
console.log(developer.basic.js); // es6

//数组:不改变原对象
newDeveloper.frameworks.push("Angular");
console.log(developer.frameworks); // [ "React", "Vue", "AngularJS" , { node: "express" } ]
newDeveloper.frameworks[3].node = "koa";
console.log(developer.frameworks); // [ "React", "Vue", "AngularJS" , { node: "express" } ]

//函数:不改变原对象
newDeveloper.summary = function () {
    console.log("I like FE development");
};
developer.summary(); // I am FE developer
涉及的知识点:

数据类型及存储机制

for...in...遍历,枚举属性

递归

对象和数组的判断

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95365.html

相关文章

  • 浅谈JavaScript 中深拷贝实现的方法

    摘要:相信人很多学习的过程中都踩了深拷贝和浅拷贝的坑,深拷贝和浅拷贝的区别我就不再赘述了,今天我来写一下我自己实现深拷贝的各种方法。中的深拷贝也是用类似方法实现。 相信人很多学习js的过程中都踩了深拷贝和浅拷贝的坑,深拷贝和浅拷贝的区别我就不再赘述了,今天我来写一下我自己实现深拷贝的各种方法。 比较简单的拷贝方式可以借用浏览器的Json对象去实现,先把对象转化为json字符串,在解析回对...

    Vicky 评论0 收藏0
  • JS里深拷贝和浅拷贝的释义

    摘要:本文解释中深拷贝和浅拷贝的区别。深拷贝深拷贝指递归的复制对象的属性给新对象。有些时候一层的深拷贝被认为是浅拷贝,比如的值是一个对象,浅拷贝出来的新对象直接引用了原对象的对象,所以也会相互影响的。 本文解释javascript中深拷贝和浅拷贝的区别。 浅拷贝/Shallow Copy 浅拷贝指拷贝了引用值。 var original = {prop1 : Prop1, prop2 : p...

    zollero 评论0 收藏0
  • 一篇文章理解JS数据类型、深拷贝和浅拷贝

    摘要:接下来我们进入正片数据类型六种基本数据类型布尔值,和一个表明值的特殊关键字。一种数据类型,它的实例是唯一且不可改变的。在中是没有方法是可以改变布尔值和数字的。参考资料深拷贝浅拷贝 前言 笔者最近整理了一些前端技术文章,如果有兴趣可以参考这里:muwoo blogs。接下来我们进入正片: js 数据类型 六种 基本数据类型: Boolean. 布尔值,true 和 false. nu...

    EddieChan 评论0 收藏0
  • 一篇文章理解JS数据类型、深拷贝和浅拷贝

    摘要:接下来我们进入正片数据类型六种基本数据类型布尔值,和一个表明值的特殊关键字。一种数据类型,它的实例是唯一且不可改变的。在中是没有方法是可以改变布尔值和数字的。参考资料深拷贝浅拷贝 前言 笔者最近整理了一些前端技术文章,如果有兴趣可以参考这里:muwoo blogs。接下来我们进入正片: js 数据类型 六种 基本数据类型: Boolean. 布尔值,true 和 false. nu...

    elisa.yang 评论0 收藏0
  • 一篇文章理解JS数据类型、深拷贝和浅拷贝

    摘要:接下来我们进入正片数据类型六种基本数据类型布尔值,和一个表明值的特殊关键字。一种数据类型,它的实例是唯一且不可改变的。在中是没有方法是可以改变布尔值和数字的。参考资料深拷贝浅拷贝 前言 笔者最近整理了一些前端技术文章,如果有兴趣可以参考这里:muwoo blogs。接下来我们进入正片: js 数据类型 六种 基本数据类型: Boolean. 布尔值,true 和 false. nu...

    enda 评论0 收藏0

发表评论

0条评论

TalkingData

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<