首页 > 代码库 > Object的原型克隆-create、assign、getPrototypeOf 方法的结合

Object的原型克隆-create、assign、getPrototypeOf 方法的结合

一、实现原型克隆

    1.1、代码

        tips:为了体现原型链,写了继承实现的代码,这部分可跳过~
    
         <script>
            /* 创建包含原型链的实验对象obj1-- start */
            function inheritPrototype(subType, superType) {
                var prototype = Object(superType.prototype);
                prototype.constructor = subType;
                subType.prototype = prototype;
            }

            function SuperType(name) {
                this.name = name;
                this.colors = [‘red‘, ‘yellow‘, ‘black‘];
            }

            SuperType.prototype.sayName = function() {
                alert(this.name);
            }

            function SubType(name, age) {
                SuperType.call(this, name);
                this.age = age;
            }

            inheritPrototype(SubType, SuperType);

            SubType.prototype.sagAge = function() {
                alert(this.age);
            };

            var obj1 = new SubType(‘puppy‘, 12);
             /* 完成实验对象obj1的创建  --end */
            
            /* 原型链克隆-- start */
            var obj2 = Object.getPrototypeOf(obj1);
            var obj3 = Object.assign(Object.create(obj2), obj1);
            /* 原型链克隆-- end */

            console.log(obj1);
            console.log(obj2);
            console.log(obj3);
        </script>
    以上代码用于验证原型链的克隆,代码分析如下。

    1.2、代码分析

        step1:设置拥有原型链的实例obj1,其属性如下:
         技术分享
        其中,自身属性:age、colors、name;原型链属性:sayAge、sayName;可忽略部分为对象的默认原型属性,本实验不考察。
 
        step2:使用 Object.getPrototypeOf() 取得实例对象obj1的原型属性对象obj2,属性如下:
        技术分享
 
        step3:使用 Object.create() 将原型属性对象obj2设置成新对象的原型属性
 
        step4:使用 Object.assign() 实现自身属性的克隆(复制),将其叠加到拥有原型属性的新对象上,完成原型链的克隆obj3。
        技术分享
        如上,通过step2-step4的过程,实现了对obj1的原型链克隆,形成新的对象obj3。

    1.3、克隆代码整合

            function clone(origin) {
                return Object.assign({}, origin);
            }
 
            function moreClone(origin) {
                let oriProto = Object.getPrototypeOf(origin);
                return Object.assign(Object.create(oriProto), origin);
            }
    函数clone为简单复制,得到原对象自身可枚举属性的克隆;
    函数moreClone可克隆原始对象的继承链及自身可枚举的属性。   
   tips:这里所用的克隆方法与JS中常说的深拷贝、浅拷贝有所区别。深拷贝、浅拷贝简单说就是看源、目标是否相互影响(自身、或者属性之类的是否指向同一个地址),如果影响就是浅拷贝,如果不影响则为深拷贝。由此看来,clone()及moreClone()均为深拷贝。

二、Object方法深入了解

    以上用到了对象的三种方法,来实现原型链的克隆。依照第一节中的实验代码,加深对这些方法的理解:

    2.1、Object.getPrototypeOf(obj1)

        概念:返回指定对象的prototype(原型);
        如1.2 step2中的图可知,其返回的原型为obj1的原型。

    2.2、Object.create(proto, [propertiesObject])

            概念:是一种新的对象创建的方法,其有两个参数:
                第一个proto,为要创建的对象的原型;
                第二个propertiesObject,为对象的属性描述符,与Object.definePropertyOf()同。
            如图:
            技术分享
            上图通过 Object.create() 分别创建 obj1 与 obj2 对应的新对象,从图中可得出以下结论:
              第一个参数:作为新对象的原型对象”__proto__”;
                  第二个参数:为属性描述符对象。(通过Object.defineProperties(obj, props)的第二个参数了解)
      所以,Object.create(proto, [propertiesObject]) 可创建一个带有原型属性的新对象。

    2.3、Object.assign(target, …sources)

        概念:将一个或多个源对象自身的所有可枚举属性 复制 到目标对象。
        如图:
            技术分享
        将obj1复制给一个空对象,可以看到obj1的原型属性未被复制。由于原型属性并非对象自身的属性,未被复制。
    

三、附加Object.defineProperty(obj, prop, descriptor)

    概念:直接在一个对象上定义新的属性或修改现有属性,并返回该对象。
    参数:obj,被操作对象;
                prop:要定义或修改的属性的名称;
                descriptor:将被定义或修改的属性的描述符
    属性的描述符相关描述如下:
        技术分享
 
    看实例:
            var obj = {};
            Object.defineProperty(obj, ‘test,  {
                configurable: false,
                enumerable: false,
                get() {
                    return this._value;
                },
                set(value) {
                    this._value = http://www.mamicode.com/value + ‘ yeap‘;
                    return true;
                }
             });
            console.log(obj.property1) //undefined
            obj.test = 2
            console.log(obj.property1) // 2 yeap    
    可以看到,给obj.test赋值时,会先通过属性描述符进行处理;通过set方法,将value处理以后,赋值给_value;当取值时,返回_value的值。
    如上,通过设置 set() 和 get() ,可对属性值的存取进行处理。该属性操作方法已广泛用于数据双向绑定的一些MVVM框架中,其中VUE就使用了该方法。其通过Object.defineProperty方法,实现setter和getter,形成依赖追踪,从而在数据被访问或修改时通知变化。
 
    tips:Object.defineProperties(obj, props)是Object.defineProperty(obj, prop, descriptor)的扩展,可一次设置多个属性的描述符。
    示例:
            Object.defineProperties(obj, {
                test1: {
                    configurable: false,
                    enumerable: false,
                    get() {
                       return this._value;
                    },
                    set(value) {
                        this._value = http://www.mamicode.com/value + ‘ yeap‘;
                        return true;
                    }
                },
                test2: {
                    value: ‘cutcut’,
                    writable: true
                }
             });
    
    
    
    
    
        

Object的原型克隆-create、assign、getPrototypeOf 方法的结合