一、实现原型拷贝

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:这里所用的拷贝方法为浅拷贝。深拷贝、浅拷贝简单说就是看源、目标的所有属性是否相互影响(自身属性、或者原型属性是否指向同一个地址),如果影响就是浅拷贝,如果不影响则为深拷贝。如果origin内有复杂类型的数据,会使得属性指向相同地址,从而使得源、目标对象之间相互影响。   

    

    如上图,对obj1的colors数据插入一个值,数组的length增1;同时,发现obj3的length也增加了1。浅拷贝得证。

    jquery的$.extend实现的深度拷贝可通过for...in实现,也就是其深拷贝是对自身的与继承的可枚举属性进行~其丢掉了原型链。所以,原型拷贝与深拷贝之间有所区别,可根据需要进行选择。在使用原生JS的环境下,可通过for...in来实现深拷贝。

    将obj1深拷贝给obj4,如下:

            let obj4 = {};
$.extend(true, obj4, obj1);
console.log(obj4);

    chrome控制台输出如下:

    

    该结构与通过for...in输出的obj1的结构相同,其丢失了obj1当中的继承的原型属性。(此处的__proto__为对象基础类型的原型属性,而非继承自自类的原型属性)。

    

    对obj1复杂类型colors插入值,obj4不受影响。深拷贝,得证。

    所以,通过for...in可实现深拷贝、Object.create()结合Object.getPrototypeOf()、Object.assign()实现原型拷贝。

    

二、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 = 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 = value + ' yeap';
return true;
}
},
test2: {
value: ‘cutcut’,
writable: true
}
});
    
    
    
    
    
        

Object的原型拷贝-create、assign、getPrototypeOf 方法的结合的更多相关文章

  1. Object.setPrototypeOf() 与Object.getPrototypeOf() 方法的使用

    Object.setPrototypeOf 方法的使用 [1] 将一个指定的对象的原型设置为另一个对象或者null(既对象的[[Prototype]]内部属性). 语法 Object.setProto ...

  2. Object.create()的使用方法

    Object.create()的使用方法:https://blog.csdn.net/wang252949/article/details/79109437

  3. [js高手之路]原型对象(prototype)与原型链相关属性与方法详解

    一,instanceof: instanceof检测左侧的__proto__原型链上,是否存在右侧的prototype原型. 我在之前的两篇文章 [js高手之路]构造函数的基本特性与优缺点 [js高手 ...

  4. JavaScript 中 Object ,Prototype 相关的属性和方法

    span { font-family: 'Consolas'; font-size: 10pt; color: #ffffff; } .sc0 { } .sc2 { color: #c0c0c0; } ...

  5. JavaScript: 认识 Object、原型、原型链与继承。

    目录 引用类型与对象 类与对象 成员组成 成员访问 实例方法 / 属性 引用类型与对象 JavaScript 存在着两种数据类型:"基本数据类型" 与 "引用数据类型&q ...

  6. Object.prototype 原型和原型链

    Object.prototype 原型和原型链 原型 Javascript中所有的对象都是Object的实例,并继承Object.prototype的属性和方法,有些属性是隐藏的.换句话说,在对象创建 ...

  7. 为什么Object.prototype在Function的原型链上与Function.prototype在Object的原型链上都为true

    关于javascript的原型链有一个问题我一直很疑惑:为什么 Function instanceof Object 与 Object instanceof Function都为true呢? Func ...

  8. JS中定义对象原型的两种使用方法

    第一种: function Person() { this.username = new Array(); this.password = "123"; } Person.prot ...

  9. Mac OSX Versions输入username按1下都会出现2个字符,并且不能create,解决方法

    我的系统,安装的versions1.3.2,下载地址:http://www.jb51.net/softs/193467.html 安装好了以后Versions输入username按1下都会出现2个字符 ...

随机推荐

  1. [转载]WCF系列_分布式事务(下)

    浏览到chnking的WCF的分布式事务处理不错,转载过来分享一下. 1. WCF分布式事务例子这里也用转账的例子说事.用户在系统A和系统B都有账户,账户间的资金可以互转,系统A的资金减少多少,系统B ...

  2. jenkins yum 安装

    jenkins yum 安装 jenkins 用过yum的方式安装:服务的启动和关闭等管理会很方便,版本升级也会变的很容易. 参考官方的说明:https://wiki.jenkins-ci.org/d ...

  3. JAVA 字符串编码转换

    /** * 字符串编码转换的实现方法 * @param str 待转换编码的字符串 * @param newCharset 目标编码 * @return * @throws UnsupportedEn ...

  4. ADO.NET操作PostgreSQL:数据库操作类(未封装)

    1.添加 /// <summary> /// 添加 /// </summary> /// <param name="newEntity">< ...

  5. 操作XDocument讲解

    1.首先建立好XML .可以通选自定义EXCEL导出XML格式的数据:(如图) 2 读取XML 文件 具体的详细讲解 可以查看 改网址 :https://blog.csdn.net/dyllove98 ...

  6. windows phone 8.0 app 移植到windows10 app笔记

    8.0 public class Convisibility : IValueConverter { public object Convert(object value, Type targetTy ...

  7. linux 配置msyql

    下面记录了如何在ubuntu16.04上安装mysql5.7的方法. sudo apt install mysql-server 安装时会让你输入mysql root用户的密码,并确认密码 sudo ...

  8. 20165219 Exp1 PC平台逆向破解

    20165219 Exp1 PC平台逆向破解 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串 ...

  9. Groovy学习记录-------Groovy安装/配置

    1.Groovy SDK下载 Groovy SDK官网下载地址: http://www.groovy-lang.org/download.html  每个版本有五个选项可供下载,依次为: binary ...

  10. Android中LayoutParams的用法

    简单说说 自己对 android LayoutParams的理解吧,xh写不出高级文章是低级写手.public static classViewGroup.LayoutParamsextends Ob ...