Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
VaJoy opened this issue Dec 9, 2015 · 19 comments
Open

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

VaJoy opened this issue Dec 9, 2015 · 19 comments

Comments

@VaJoy
Copy link
Member

VaJoy commented Dec 9, 2015

需求

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

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

  • 传入一个参数 obj1,判断其是否对象类型,若不是则返回空对象{}
  • 若传入参数为对象类型,则返回深拷贝后的新对象,使其满足如下代码:
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
Copy link

inJs commented Dec 9, 2015

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
Copy link

gaozejie commented Dec 9, 2015

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

@wanglianjie91
Copy link

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
Copy link
Member

LeoHuiyi commented Dec 9, 2015

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
Copy link
Member

tudousi commented Dec 9, 2015

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
Copy link

function deepCopy(obj){
    if(obj != null){
        var newObj = Object.create(obj);
        return newObj;
    }
    else{throw new TypeError(obj + ' is null or undefined');}
}

@SearChen
Copy link

SearChen commented Dec 9, 2015

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
Copy link
Member

kitebear commented Dec 9, 2015

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

@VaJoy
Copy link
Member Author

VaJoy commented Dec 9, 2015

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

@bluesrocker
Copy link

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
Copy link

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

@VaJoy
Copy link
Member Author

VaJoy commented Dec 9, 2015

@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
Copy link

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

@coxo
Copy link
Member

coxo commented Dec 10, 2015

可以看看

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;
    }
  });
}

@VaJoy VaJoy added the js label Dec 11, 2015
@wait-hua
Copy link

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
Copy link

overkazaf commented Dec 24, 2015

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
Copy link

aaronlamz commented Apr 17, 2016

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
Copy link

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

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
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests