23.js中深拷贝的实现

2018-04-30  本文已影响0人  jqClub

1.javaScript的变量类型
(1)基本类型:
5种基本数据类型Undefined、Null、Boolean、Number 和 String,变量是直接按值存放的,存放在栈内存中的简单数据段,可以直接访问。

(2)引用类型:
存放在堆内存中的对象,变量保存的是一个指针,这个指针指向另一个位置。当需要访问引用类型(如对象,数组等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。

2.深拷贝的实现
2.1、Array的slice和concat方法(实际上是浅拷贝)

var array = [1,2,3]; 
var array_concat = array.concat(); 
var array_slice = array.slice(0); 

//缺点:数组中的对象元素(Object,Array等)只是复制了引用
var array = [1, [1,2,3], {name:"array"}]; 
var array_concat = array.concat();

2.2、JSON对象的parse和stringify

var source = { name:"source", child:{ name:"child" } } 
var target = JSON.parse(JSON.stringify(source));
//缺点:对于正则表达式类型、函数类型等无法进行深拷贝(而且会直接丢失相应的值)。并且会抛弃对象的constructor

2.3、简易版本1

var deepCopy = function(obj) {
    if (typeof obj !== 'object') return;
    var newObj = obj instanceof Array ? [] : {};
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
        }
    }
    return newObj;
}

2.4、简易版本2

function deepClone (obj) {
  if (Array.isArray(obj)) {
    return obj.map(deepClone)
  } else if (obj && typeof obj === 'object') {
    var cloned = {}
    var keys = Object.keys(obj)
    for (var i = 0, l = keys.length; i < l; i++) {
      var key = keys[i]
      cloned[key] = deepClone(obj[key])
    }
    return cloned
  } else {
    return obj
  }
}

2.5、另一种实现

(function ($) {
    'use strict';

    var types = 'Array Object String Date RegExp Function Boolean Number Null Undefined'.split(' ');

    function type () {
       return Object.prototype.toString.call(this).slice(8, -1);
    }

    for (var i = types.length; i--;) {
        $['is' + types[i]] = (function (self) {
            return function (elem) {
               return type.call(elem) === self;
            };
        })(types[i]);
    }

    return $;
})(window.$ || (window.$ = {}));//类型判断

function copy (obj,deep) { 
    if ($.isFunction(obj)) {
        return new Function("return " + obj.toString())();
    } else if (obj === null || (typeof obj !== "object")) { 
        return obj; 
    } else {
        var name, target = $.isArray(obj) ? [] : {}, value; 

        for (name in obj) { 
            value = obj[name]; 

            if (value === obj) {
                continue;
            }

            if (deep) {
                if ($.isArray(value) || $.isObject(value)) {
                    target[name] = copy(value,deep);
                } else if ($.isFunction(value)) {
                    target[name] = new Function("return " + value.toString())();
                } else {
                    target[name] = value;
                } 
            } else {
                target[name] = value;
            } 
        } 
        return target;
    }         
}

2.6、第三方库的实现

jQuery —— $.clone() / $.extend()
Underscore —— _.clone()
lodash —— _.clone() / _.cloneDeep()

参考:
1.JavaScript专题之深浅拷贝
2.javaScript中浅拷贝和深拷贝的实现
3.深入剖析 JavaScript 的深复制

上一篇 下一篇

猜你喜欢

热点阅读