JavaScript中的拷贝

原文地址
要说 JavaScript 的拷贝问题,首先要了解的是 JavaScript 的数据类型。
在 JavaScript 中数据类型大致可以分成三类,分别是基本数据类型、引用数据类型和特殊数据类型。
基本数据类型有:NumberStringBoolean
引用数据类型有:Object(其中包含Array, Object, Date, RegExp)
特殊数据类型:NullUndefined
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。所以现在JavaScript中一共有7种数据类型。

其中特殊类型Undefined是变量声明了但是没有赋值,Null表示一个无的对象是一个Object,这两者在判断语句中都会被转成false,其实都是表示没有,但为什么要有两个,说起来比较复杂,可以看看阮老师的文章undefined与null的区别

继续往下说,下面简单说说基本数据类型和引用数据类型的区别。
最大的区别就是,基本数据类型的变量标识符和变量值都存在栈内存,而引用类型在栈内存中存储的是变量标识符和指针,然后在堆内存中保存对象内容。如下图:

基本类型引用类型存储示意图

现在开始说拷贝的问题,基本数据类型,我们直接

let a = 1;
let a1 = a;

就可以了。而如果是引用类型这样的话

let b = {a: 1};
let b1 = b;

此时bb1的值就会互相影响也就是改变了他们中任何一个值,另外一个值也会相应的改变。
来个图:

基本类型和引用类型的普通拷贝

由此可见使用=的方式对于基本类型是有效的而对于引用类型是不可以的。

在jQuery中我们可以直接使用jQuery的extend()方法来进行深拷贝。

使用原生JavaScript我们应该这么做呢?

如果是Array,且数组中的数据都是基本数据类型,我们可以利用数组中的slice()方法来返回一个新的数组,像这样:

let arrA = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let arrA1 = arrA.slice();

如果是Object的keyValuePair,且对应的value都是基本数据类型,则可以用Object.assign()来操作。

let a = {a: 1};
let a1 = Object.assign({}, a);

上述两种方法,只能在特定的情况下有用,一旦数组的值是引用类型或者对象中value的值是一个引用类型,就不起作用了。如果遇到复杂的数据类型该怎么进行深拷贝呢?以前在不少帖子里看过说使用JSON来做个中转,类似于这样:

let a = {a: {a : {a: 1}}};
let a1 = JSON.parse(JSON.stringify(a));

这个方法好像很无敌,貌似无论多么复杂的数据类型都能深拷贝,但是一旦遇到key对应的value是Function或者其他JSON不支持的类型就不行了,可以参照stackoverflow上的这个回答javascript deep copy using JSON

所以在JavaScript中深拷贝是一件非常费事的事情。大部分情况下我们并不需要深拷贝,再仔细看看自己写的函数非得深拷贝不可吗?

恩,如果你非要!

  1. 看看jQuery extend()方法的具体实现,这里有个参考资料jQuery源码
  2. 使用lodash的cloneDeep()方法实现比较复杂,当然也比较好
  3. 再贴一个stackoverflow上的回答How to Deep clone in javascript
function clone(item) {
    if (!item) { return item; } // null, undefined values check

    var types = [ Number, String, Boolean ], 
        result;

    // normalizing primitives if someone did new String('aaa'), or new Number('444');
    types.forEach(function(type) {
        if (item instanceof type) {
            result = type( item );
        }
    });

    if (typeof result == "undefined") {
        if (Object.prototype.toString.call( item ) === "[object Array]") {
            result = [];
            item.forEach(function(child, index, array) { 
                result[index] = clone( child );
            });
        } else if (typeof item == "object") {
            // testing that this is DOM
            if (item.nodeType && typeof item.cloneNode == "function") {
                var result = item.cloneNode( true );    
            } else if (!item.prototype) { // check that this is a literal
                if (item instanceof Date) {
                    result = new Date(item);
                } else {
                    // it is an object literal
                    result = {};
                    for (var i in item) {
                        result[i] = clone( item[i] );
                    }
                }
            } else {
                // depending what you would like here,
                // just keep the reference, or create new object
                if (false && item.constructor) {
                    // would not advice to do that, reason? Read below
                    result = new item.constructor();
                } else {
                    result = item;
                }
            }
        } else {
            result = item;
        }
    }

    return result;
}
  1. 自己撸一个...
  2. 待我有空撸一个(逃
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,682评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,277评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,083评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,763评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,785评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,624评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,358评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,261评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,722评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,900评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,030评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,737评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,360评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,941评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,057评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,237评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,976评论 2 355

推荐阅读更多精彩内容