一个对象和另一个对象之间2:赋值和克隆

当我们操作两个对象的时候
1.0 赋值

var obj = {
        age: 123,
        name : 'mike',
        son : {
          age : 18,
          name : 'peter'
        }
      }
      var newObj = obj;
      
      newObj.name = 'kaisa';
      console.log(obj);

赋值操作,两个变量指向同一个地址,
除非 newObj = newnewObj,
否则 obj和 newObj是互相影响的.

我们也可以看成 数据的流向是双向的.
我们有时希望这样,
但有时我们也希望能毫无关系.互不影响.

2.0深度克隆

function clone (origin, target) {
        var target = target || {};
          for(var key in origin){
            if(origin[key] !== null && origin.hasOwnProperty(key)){
            if(typeof(origin[key]) == 'object'){
                console.log(origin.hasOwnProperty(key),key);
                if(Object.prototype.toString.call(origin[key]) == '[object Array]'){
                  target[key] = [];
                }else{
                  target[key] = {};
                }
                clone(origin[key],target[key]);
            }else {
              target[key] = origin[key];
            }
          }
         }
        return target;
      }
      var newObj = [];
      clone(obj,newObj);
      console.log(newObj);
      newObj.name = 'kaisa';
      console.log(obj);
      console.log(newObj);

你发现,两个对象一样,但互不影响.
但我们知道一个对象不只是他自己,还包括他的原型链

3.0 对象间继承

最简单的是这样
function Obj () {}
var obj = new Obj();
var newObj = Object.create(obj);
这样就能继承obj以及obj上的原型链
或者其实1.0版本赋值也可以做到,因为本质上是同一个对象.

那我们有没有办法深度克隆的同时,还能继承?
最简单的方法是
var newObj = new Obj()
这样的话,出来的基本上一样,又能继承.

那我们就想克隆obj的同时,想要继承呢?

也许可以
var newObj = Object.create(obj);
然后调用2.0
clone(obj,newObj);

      Person.prototype.name = 'mike';
      Person.prototype.aaa = 'bbb';
      
      function Person () {
        
      }
      
      var obj = new Person();
      obj.age = 18;
      obj.son = {
        name : 'peter',
        age : 5
      }
      var newObj = Object.create(obj);
      clone(obj,newObj);
      console.log(newObj);
      newObj.age = 99;
      console.log(obj);
      console.log(newObj);
      
      console.log(obj.name);
      console.log(newObj.name);//竟然可以

我本来以为不可以,后来发现,clone函数里从头到尾都没有对 target = 赋值,所以target地址是没有变化的,所以可以继承.这就把我给逗乐了.

既然如此,能不能把两个步骤写在一起?

4.0 继承版深度克隆

Person.prototype.name = 'mike';
      
      function Person () {
        
      }
      
      var obj = new Person();
      obj.age = 18;
      obj.son = {
        name : 'peter',
        age : 5
      }
      
      function clone (origin,target,flag) {
        if(!flag){
          var target = Object.create(origin);
          flag = true;
        }else{
          var target = target;
        }
          for(var key in origin){
            if(origin[key] !== null && origin.hasOwnProperty(key)){
            if(typeof(origin[key]) == 'object'){
                if(Object.prototype.toString.call(origin[key]) == '[object Array]'){
                  target[key] = [];
                }else{
                  target[key] = {};
                }
                clone(origin[key],target[key],flag);
            }else {
              target[key] = origin[key];
            }
          }
         }
        return target;
      }
      var newObj = clone(obj,newObj);
      console.log(newObj);
      newObj.age = 99;
      console.log(obj);
      console.log(newObj);
      console.log(obj.name);
      console.log(newObj.name);

但这个版本有个问题, 那就是 必须要接收返回值,newobj = clone(obj,newObj);//括号里的newOjb实际上不用传,因为不会起效果

最近看学习q源码
有个extend继承跟本篇内容有很大的相关性
jq extend 源码笔记 https://www.jianshu.com/p/6d033fa5c39e

你可能感兴趣的:(一个对象和另一个对象之间2:赋值和克隆)