1.以复制方式实现的继承

1.1浅拷贝

基本类型的复制

 var parent = {
lanage: "chinese"
} var child = {
name: "xxx",
age: 12
} function extend(parent, child) {
var child = child || {};
for (const propertype in parent) {
child[propertype] = parent[propertype];
}
} extend(parent, child); console.log(child);//{ name: 'xxx', age: 12, lanage: 'chinese' }

以上代码中,通过一个extend()函数,将父对象parent的属性遍历赋给子对象child,从而实现继承。

但是这种字面量复制的方式存在巨大的缺陷,当父对象有引用类型的属性时,通过这么复制的方式,就像上一节中的var b = a一样,只会将a对象的引用赋给b对象,结果两者是指向同一个对象内存的,继承出来的子对象的属性是同一个,显然是不能满足需求的,(基本类型之间画等号是值的复制,引用类型之间画等号是引用的复制)所以就需要另谋出路。

1.2.深拷贝

利用递归加类型判断复制引用类型

 var parent = {
lanage: "chinese",
address: {
home: "gansu",
office: "xian"
},
schools: ["xiaoxue", "zhongxue", "daxue"]
} var child = {
name: "xxx",
age: 12
} function extendDeeply(parent, child) {
var child = child || {};
for (const propertype in parent) {
//首先判断父对象的当前属性是不是引用类型
if (typeof parent[propertype] === "object") {
//再判断该引用类型是不是数组,是则给子对象初始化为空数组,否则初始化为空对象
child[propertype] = Array.isArray(parent[propertype]) ? [] : {};
//递归调用自己,将父对象的属性复制到子对象
extendDeeply(parent[propertype], child[propertype]);
} else {
//基本类型直接复制
child[propertype] = parent[propertype];
}
}
} extendDeeply(parent, child);
console.log(child);
child.schools[0] = "qinghua"; //改变子对象的属性值
child.address.home = "tianjin"; console.log(child.schools[0]); //qinghua
console.log(parent.schools[0]); //xiaoxue
console.log(child.address.home); //tianjin
console.log(parent.address.home); //gansu

可见此时子对象的改变并不会影响到父对象,父子彻底决裂。这便是深拷贝实现的继承。

注意:for in 是可以遍历数组的,结果为数组元素下标。

2.以构造函数实现继承

 function Parent() {
this.name = "name";
this.age = 12;
} function Child() {
Parent.call(this);
this.language = "chinese";
} var child = new Child();
console.log(child);//{ name: 'name', age: 12, language: 'chinese' }
child.name = "swk";
console.log(new Parent().name);//name

如上所示,通过在子类构造函数中调用父类构造函数,将父类属性继承到子类对象上,new出来的每一个子类对象都是独立的实例,这种方式更符合面向对象的思想。

3.以原型方式实现继承

 var person = {name: "pname"};

 function myCreate(person) {
var ins;
function F() { };
F.prototype = person;
ins = new F();
return ins;
} var c = new myCreate(person);
console.log(c.name); //pname
console.log(c); //{}

如上所示,将一个构造函数的原型替换为父对象,然后返回该构造函数的实例,如此一来创建的子对象就是F的实例,并且其原型为父对象,所以c.name可以被查找到,但子对象c本身是没有属性的。这种直接重写prototype原型对象的弊端在于会断掉原本的原型链,即没有了继承自Object的方法,和给原型对象prototype上添加属性是不同的。

4.JS原型链

盗一波大神的经典图

从该图可以看出两点

4.1从原型prototype层面:

  • 不论是 new Foo()自定义构造函数,new Object()系统构造函数,还是对象字面量创建出来的对象,只要是对象,其原型最终都指向Object.prototype对象,自定义的多绕了一步,就像Java里说的,Object.prototype是一切JS对象的根对象。
  • 函数的原型都指向Function.prototype,而在JS中,函数也是对象的一种,所以符合第一条。

4.2从构造器constructor层面

  • 首先对象的构造器肯定是指向他的构造函数,f1, f2指向Foo(), o1, o2指向Object()。
  • 而构造函数Foo()和Object()的constructor属性最终指向函数构造器Function()。

JS对象继承与原型链的更多相关文章

  1. 一步步学习javascript基础篇(5):面向对象设计之对象继承(原型链继承)

    上一篇介绍了对象创建的几种基本方式,今天我们看分析下对象的继承. 一.原型链继承 1.通过设置prototype指向“父类”的实例来实现继承. function Obj1() { this.name1 ...

  2. JS面向对象(2) -- this的使用,对象之间的赋值,for...in语句,delete使用,成员方法,json对象的使用,prototype的使用,原型继承与原型链

    相关链接: JS面向对象(1) -- 简介,入门,系统常用类,自定义类,constructor,typeof,instanceof,对象在内存中的表现形式 JS面向对象(2) -- this的使用,对 ...

  3. JS function 是函数也是对象, 浅谈原型链

    JS function 是函数也是对象, 浅谈原型链 JS 唯一支持的继承方式是通过原型链继承, 理解好原型链非常重要, 我记录下我的理解 1. 前言 new 出来的实例有 _proto_ 属性, 并 ...

  4. js继承之原型链方式实现

    温故而知新: 在之前的文章已经重点了解了原型对象,今天就理一理这个原型对象在原型链式的继承中的使用 function a(x,y){this.x=x;this.y=y;} //定义一个函数,当构造函数 ...

  5. JS对象继承篇

    JS对象继承篇 ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现的 原型链 其基本思路是利用原型让一个引用类型继承另一个引用类型的属性和方法 function Person() ...

  6. (翻译) Inheritance and the prototype chain 继承和原型链

    JavaScript is a bit confusing for developers experienced in class-based languages (like Java or C++) ...

  7. JavaScript之继承(原型链)

    JavaScript之继承(原型链) 我们知道继承是oo语言中不可缺少的一部分,对于JavaScript也是如此.一般的继承有两种方式:其一,接口继承,只继承方法的签名:其二,实现继承,继承实际的方法 ...

  8. 一篇JavaScript技术栈带你了解继承和原型链

    作者 | Jeskson 来源 | 达达前端小酒馆 1 在学习JavaScript中,我们知道它是一种灵活的语言,具有面向对象,函数式风格的编程模式,面向对象具有两点要记住,三大特性,六大原则. 那么 ...

  9. 关于JavaScript的原型继承与原型链

    在讨论原型继承之前,先回顾一下关于创建自定义类型的方式,这里推荐将构造函数和原型模式组合使用,通过构造函数来定义实例自己的属性,再通过原型来定义公共的方法和属性. 这样一来,每个实例都有自己的实例属性 ...

随机推荐

  1. centos7.x86_64搭建饥荒服务器

    http://blog.ttionya.com/article-1233.html 在centos7下找不到 libcurl-gnutls.so.4,而且必须要安装32位的才行 yum install ...

  2. JConsole远程监控Tomcat7

    下面技术应用于最优质的水果的鲜果篮 一.设置服务端: 1.增加Listener到conf/server.xml <Listener className="org.apache.cata ...

  3. HTML5 界面元素 Canvas 參考手冊

    HTML5 界面元素 Canvas 參考手冊 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协 ...

  4. Compile OpenCASCADE7.3 with VS2008

    Compile OpenCASCADE7.3 with VS2008 eryar@163.com 概述 在OpenCASCADE的源码文件夹中有个adm文件夹,里面提供了各个平台中编译源码的项目文件. ...

  5. Datazen图表创建和公布

     Datazen是被微软收购的移动端全平台的数据展现解决方式.此篇主要介绍怎样创建和公布图表. 如前面介绍,Datazen图表的创建和公布是通过Publisher的应用,它是Windows 8应用 ...

  6. 福利贴——爬取美女图片的Java爬虫小程序代码

    自己做的一个Java爬虫小程序 废话不多说.先上图. 目录命名是用标签缩写,假设大家看得不顺眼能够等完成下载后手动改一下,比方像有强迫症的我一样... 这是挂了一个晚上下载的总大小,只是还有非常多由于 ...

  7. IIS访问站点,出现connection refused

    排查后,发现是因为使用了代理导致的. 需要设置 Don't use the proxy server for local addresses.

  8. react --- 路由传参的几种方式

    1.params 优势 : 刷新地址栏,参数依然存在缺点:只能传字符串,并且,如果传的值太多的话,url会变得长而丑陋. 2.query 优势:传参优雅,传递参数可传对象:缺点:刷新地址栏,参数丢失 ...

  9. 显示gif动画(帧动画的播放)

    在android上显示gif不太方便,虽然有控件可以实现,但是效果不是很好,保险点儿的作法还是使用帧动画来处理.①在XML中定义animation-list:<?xml version=&quo ...

  10. 51Nod 1010 只包含因子2 3 5的数(打表+二分)

    K的因子中只包含2 3 5.满足条件的前10个数是:2,3,4,5,6,8,9,10,12,15. 所有这样的K组成了一个序列S,现在给出一个数n,求S中 >= 给定数的最小的数. 例如:n = ...