迅雷面试题:深拷贝对象,除了原型上的属性?

我的解决方法是:参考jquery中extend方法的实现,通过isPlainObject 函数判断该对象是否具有通过构造函数继承的原型上的属性。
请问,我这个解决方法有什么问题吗?

 isPlainObject = function(obj) {
          if (obj.constructor && !hasOwn.call(obj, "constructor")
            && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
            return false;
          }
          var key;
          for (key in obj) {
          }
          return key === undefined || hasOwn.call(obj, key);
},
        
       
 //测试,对于对象x不进行深拷贝
function O() {
  this.yyy = 'yyy';
}
function X() {
  this.xxx = 'xxx';
}
X.prototype = new O();
x = new X();

obj1 = { a : 'a', b : 'b', y : '1'  };
obj2 = {  x : { xxx : 'xxx', yyy : 'yyy' },  y : 'y' };
var combineObj = $.extend(true,obj1,obj2);
console.log(combineObj);

阅读 3.2k
4 个回答
//判断是对象
var isObject = function(obj){
    return Object.prototype.toString.call(obj) === '[object Object]'
}
//判断是数组
var isArray = Array.isArray || function(obj){
    return Object.prototype.toString.call(obj) === '[object Array]'
}
//获取对象不在原型上的键
var get_keys = function(obj){
    var keys = [];
    for(key in obj){
        if(hasOwnProperty.call(obj,key)){
            keys.push(key);
        }
    }
    return keys;
}

//实现深拷贝
var deepCopy = function(obj){
    var temp ;
    if(isArray(obj)){
        temp = [];
        for(var i = 0 ; i < obj.length ; i++){
            if(isArray(obj[i])||isObject(obj[i])){
                //当前项是数组或者对象,递归调用
                temp.push(deepCopy(obj[i]));
            }else{
                temp.push(obj[i]);
            }
        }
    }else if(isObject(obj)){
        temp = {};
        var keys = get_keys(obj);
        var length = keys.length ;
        for(var i = 0 ; i < length ; i++){
            //将对象值递归,结果赋值到新创建的temp对象的key[i]属性。
            temp[keys[i]] = deepCopy(obj[keys[i]])
        }
    }else{
        //传入其他类型直接返回。
        return obj;
    }
    return temp ;
}

刚好写了这方面的内容
function Copy(p, c) {

var c = c || {};
for (var i in p) {
  if (typeof p[i] === 'object') {
     c[i] = (p[i].constructor === Array) ? [] : {};
     Copy(p[i], c[i]);
  } else {
     c[i] = p[i];
  }
}
return c;
}    

a.key2 = ['小辉','小辉'];
var b={};
b = Copy(a,b);
b.key2.push("大辉");
alert(b.key2); //小辉,小辉,大辉
alert(a.key2); //小辉,小辉

1.你获取对象原型的方法不对,obj.constructor.prototype 不等于obj的原型,且不说constructor是一个可以被修改的属性,在一个对象用Object.create的方法创建时就不等于

let a = {name: 'create'}
let b = Object.create(a)
b.__proto__ // a
b.constructor.prototype // Object.prototype

直接用Object.getPrototypeOf就行了

2.不是很懂“判断该对象是否具有通过构造函数继承的原型上的属性”这句话,为什么要判断?我只需要知道这个属性是对象本身的还是原型上的就行了,它怎么来的无所谓

3.面试来说的话,感觉你没答到点子上,首先关于原型的知识,如何获取原型?如何判断属性(方法)是本身的还是原型的?这些是要在代码里体现(聊一聊)的,然后题目说”除了原型链上的属性“,我的理解是原型链的属性不复制,方法要复制,那么如何区分方法(function)和属性?还有深拷贝的常见问题,对象和数组如何处理?函数如何处理(要不要克隆),都要提到,这样就可以一直往下聊

直接黑科技多好
var obj = JSON.parse(JSON.stringify(obj))

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题