N-ZOO / everycode

前端每日一练
163 stars 18 forks source link

[js]实现一个深拷贝方法 #1

Open VaJoy opened 8 years ago

VaJoy commented 8 years ago

需求

深拷贝指的是在复制对象时,该对象属性所引用的对象全部进行新建对象复制,以保证深拷贝后的对象属性不存在任何对原对象属性的引用,从而避免用户修改新对象属性值的同时也改变了其指向的旧对象属性。

请你靠自己写一个深拷贝的实现接口 deepCopy:

var obj1 = {
    a: 1,
    b: {m: 2},
    c: [9, 0]
};

var obj2 = deepCopy(obj1);

obj2.b = {m: 11};
obj2.c = 1;
console.log(obj1.b.m);  //打印2,而不是11
console.log(obj1.c);  //打印数组[9, 0],而不是1

function deepCopy(obj) {
    //TODO: 实现深拷贝
}
inJs commented 8 years ago
function deepClone(obj) {
            var copyOfObj;
            if (obj){
                if (obj.constructor == Object || obj.constructor == Array) {
                    copyOfObj = new obj.constructor();
                } else {
                    copyOfObj = new obj.constructor(obj.valueOf());
                }
                for (var key in obj) {
                    if (copyOfObj[key] != obj[key]) {
                        if (typeof (obj[key]) == 'object') {
                            copyOfObj[key] = arguments.callee(obj[key]);
                        }
                        else {
                            copyOfObj[key] = obj[key];
                        }
                    }
                }
                copyOfObj.toString = obj.toString;
                copyOfObj.valueOf = obj.valueOf;
            }
            return copyOfObj;
}
gaozejie commented 8 years ago
function deepCopy(obj) {
    //TODO: 实现深拷贝
  var newObj;
  newObj = obj.constructor == Object?Object.create(obj):{};
  return newObj;
}
wanglianjie91 commented 8 years ago
function deepCopy(obj) {
    var newObj = {};
    if(!obj instanceof Object){
        return newObj;
    }

    for(var i in obj){
        if(obj[i] instanceof Object){
            newObj[i] = deepCopy(obj[i]);
        }else{
            newObj[i] = obj[i];
        }       
    }
    return newObj;
}
LeoHuiyi commented 8 years ago
var deepCopy = function() {
        var rtoType = /\s([a-zA-Z]+)/,
            toType = function(obj) {
                return ({}).toString.call(obj).match(rtoType)[1].toLowerCase();
            },
            isArray = Array.isArray || function(obj) {
                return toType(obj) === 'function';
            };

        return function deepCopy(obj) {
            var newObj = toType(obj) === 'object' ? {} : isArray(obj) ? [] : false;

            if (newObj) {
                var prop, val;

                for (prop in obj) {
                    val = obj[prop];

                    if (toType(val) === 'object' || isArray(val)) {
                        newObj[prop] = deepCopy(val);
                    } else {
                        newObj[prop] = val;
                    }
                }

                return newObj;
            }

            return {};
        }
    }();
tudousi commented 8 years ago
function deepCopy(obj) {
    var ret = {};
    if(typeof obj != 'object' || obj.length) {
        return ret;
    }
    for(var key in obj) {
        if(typeof obj[key] != 'object'  || obj[key].length) {
            ret[key] = obj[key];
        }else{
            ret[key] = deepCopy(obj[key]);
        }
    }
    return ret;
}
var obj1 = {
    a: 1,
    b: {m: 2},
    c: [9, 0]
};
var obj2= deepCopy(obj1);
obj2.b = {m: 11};
obj2.c = 1;

console.log(obj1,obj2)
console.log(obj1.b.m);  //打印2,而不是11
console.log(obj1.c);  //打印数组[9, 0],而不是1

实现方法略屌丝 = =

bluesrocker commented 8 years ago
function deepCopy(obj){
    if(obj != null){
        var newObj = Object.create(obj);
        return newObj;
    }
    else{throw new TypeError(obj + ' is null or undefined');}
}
SearChen commented 8 years ago
function deepCopy(source){
  if(source!=null){
    var rest = {};
    for(var key in source){
     if(typeof source[key] =="object"){
       rest[key] = deepCopy(source[key]);
     }else{
       rest[key] = source[key];
     }

    }
    return rest;
  }
}
kitebear commented 8 years ago

题目要求 保证深拷贝后的对象属性不存在任何对原对象属性的引用 在这里包括原型的引用 所以用object.create() 可以想想别的办法

VaJoy commented 8 years ago

@Mrxdh 我觉得使用 object.create 是个有趣的方法,它创建出来的新对象对旧对象的继承事实上是以__proto__内部原型的形式在引用的,而__proto__你是无法修改它的,所以它的实现很有趣

bluesrocker commented 8 years ago
function deepCopy(oldObj, changedObj){
    var addObj = changedObj || {};
    for(var i in oldObj){
        if( oldObj.hasOwnProperty(i) ){
            if(typeof oldObj[i] === 'object'){
                addObj[i] = Array.isArray(oldObj[i]) ? [] : {};
                deepCopy2(oldObj[i], addObj[i]);
            }
            else{
                addObj[i] = p[i];
            }
        }
    }
    return addObj;
};
bluesrocker commented 8 years ago

Object.create()是应题的, 本质上新对象是不能修改老对象的. 我后面提供的这个方法有点粗糙, 在考虑是否要使用oldObj.hasOwnProperty

VaJoy commented 8 years ago

@bluesrocker 对于本题需求的确应题,但是,拿来做深拷贝实现其实不合适。 原因如同我上述说的,新对象的__proto__指向了旧对象,的确新对象的改变不影响旧对象,但是旧对象的改变就会影响新对象的默认值了,比如这样:

    var obj1 = {
        a: 1,
        b: {m: 2},
        c: [9, 0]
    };

    var obj2 = deepCopy(obj1);

    function deepCopy(obj) {
        //TODO: 实现深拷贝
        var newObj;
        newObj = obj.constructor == Object?Object.create(obj):{};
        return newObj;
    }

    obj1.a = 2;
    console.log(obj2.a);  //新对象也变成2了
bluesrocker commented 8 years ago

@VaJoy 你说的对, 我没有想到旧对象修改会影响新对象的默认值.

coxo commented 8 years ago

可以看看

Object.assign({}, obj);

code:

if (!Object.assign) {
  Object.defineProperty(Object, 'assign', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(target) {
      'use strict';
      if (target === undefined || target === null) {
        throw new TypeError('Cannot convert first argument to object');
      }

      var to = Object(target);
      for (var i = 1; i < arguments.length; i++) {
        var nextSource = arguments[i];
        if (nextSource === undefined || nextSource === null) {
          continue;
        }
        nextSource = Object(nextSource);

        var keysArray = Object.keys(nextSource);
        for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
          var nextKey = keysArray[nextIndex];
          var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
          if (desc !== undefined && desc.enumerable) {
            to[nextKey] = nextSource[nextKey];
          }
        }
      }
      return to;
    }
  });
}
wait-hua commented 8 years ago
function deepCopy(obj) {
    var copyObj = new Object();
    for(var i in obj) {
        if(typeof obj[i] === "object") {

            copyObj[i] = deepCopy(obj[i]);
        } else {
            copyObj[i] = obj[i];
        }
    }
    return copyObj;
}
overkazaf commented 8 years ago
function deepCopy(obj) {
    if (typeof(obj) !== 'object' || obj === null || obj === undefined) return obj;
    var re = new obj.constructor();
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
          re[key] = deepCopy(obj[key]);
        }
    }
    return re;
}
aaronlamz commented 8 years ago
function deepCopy(obj) {
    var o;
    switch (typeof obj) {
        case "undefined":
            break;
        case "string":
            o = obj + "";
            break;
        case "number":
            o = obj - 0;
            break;
        case "boolean":
            o = obj;
            break;
        case "object": // object 分为两种情况 对象(Object)或数组(Array)
            if (obj === null) {
                o = null;
            } else {
                if (Object.prototype.toString.call(obj).slice(8, -1) === "Array") {
                    o = [];
                    for (var i = 0; i < obj.length; i++) {
                        o.push(deepCopy(obj[i]));
                    }
                } else {
                    o = {};
                    for (var k in obj) {
                        o[k] = clone(obj[k]);
                    }
                }
            }
            break;
        default:
            o = obj;
            break;
    }
    return o;
}

来一个:)

sevenCon commented 8 years ago

=.=,哎,书到用时方恨少

function deepCopy(obj){
    var r={};
    if (!Object.prototype.toString.apply(obj) ==='[object Object]') return;
    for(var i in obj){
         r[i] = typeof obj[i] ==='object'?deepCopy(obj[i]):obj[i];
    }
    return r;
}
TheSunRisesAsUsual commented 5 years ago

function deepCopy(obj){ return typeof obj === "object" ? JSON.parse(JSON.stringify(obj)) : {}; }