1、原型链继承

直接将子类型的原型指向父类型的实例,即“子类型.prototype = new 父类型();”,实现方法如下:

//父类构造函数
function father(name) {
this.name = name;
this.colors = ['red'];
}
//父类添加属性
father.prototype.sayName = function() {
console.log(this.name);
}
//子类构造函数(声明)
function son(name,age) {
this.age = age;
}
// 实现继承的关键步骤,子类型的原型指向父类型的实例
son.prototype = new father(); // 在此处给子类型添加方法,一定要在实现继承之后,否则会在将指针指向父类型的实例,那么方法就为空(被父类型给覆盖了)
son.prototype.sayAge = function() {
console.log(this.age);
} var tmp1 = new son('try',18);
console.log(tmp1.colors); //'red'
tmp1.sayAge(); var tmp2 = new son();
tmp2.colors.unshift('yellow');
console.log(tmp1.colors); //'yellow','red'

以上代码不难看出,有两个问题

  1. 原型链方式可以实现所有属性方法共享,但无法做到属性、方法独享
  2. 在创建子类型的实例时,不能向父类型的构造函数中传递参数。实际上是没有办法在不影响所有对象实例的情况下,给父类型的构造函数传递参数

    基于此,实践中很少单独使用原型链。

2、借用构造函数

为了解决上面两个问题,出现了这种方法。在子类型的构造函数内调用父类型的构造函数,函数只不过是在特定环境中执行代码的对象,因此可以通过apply()或call()方法执行构造函数

除了能独享属性、方法外还能在子类构造函数中传递参数,但代码无法复用。

function father(name) {
this.name = name;
this.colors = ['red'];
this.test = function() {
console.log('test success');
}
}
father.prototype.sayName = function() {
console.log(this.name);
} function son(name,age) {
//就只是加了下面这句
father.apply(this);
this.age = age;
} var tmp1 = new son('try',18);
console.log(tmp1.colors); //'red'
tmp1.sayName(); //error!
tmp1.test(); //OK var tmp2 = new son();
tmp2.colors.unshift('yellow');
console.log(tmp1.colors); // 'red'

不难发现,这种方法也有一个超大的问题。子类只能调用父类构造函数里的函数(如上面的test),对于其后面定义在其属性里的函数(如上面的sayName)就无法调用了。因此函数复用就无从谈起了。

3、组合继承

顾名思义,组合,就是将上两种方式组合在一起,从而发挥二者之长的一种继承模式。使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现堆实例属性的继承

分别是 son.prototype = new father(); apply(this);

但混合模式也并非没有缺点,在继承方法的时候实际已经继承了父类型的属性,只不过此时对于引用类型属于共享的;

因此在子类型的构造函数内再次调用父类型的构造函数从而继承了父类型的属性而去覆盖了原型中所继承的属性。

即调用了两次父类构造函数


function father(name) {
this.name = name;
this.colors = ['red'];
this.test = function() {
console.log('test success');
}
}
father.prototype.sayName = function() {
console.log(this.name);
} function son(name,age) {
father.apply(this); //一次调用
this.age = age;
}
son.prototype = new father(); //两次调用
var tmp1 = new son('try',18);
console.log(tmp1.colors); //'red'
tmp1.sayName(); //error!
tmp1.test(); //OK var tmp2 = new son();
tmp2.colors.unshift('yellow');
console.log(tmp1.colors); // 'red'

4、原型式继承(寄生和这个差不多 不单独介绍了,但寄生有增强对象的过程 即构造函数指向自己)

和原型链唯一的不一样在于,原型式继承 就是不用实例化父类了,直接实例化一个临时副本实现了相同的原型链继承。(即子类的原型指向父类副本的实例从而实现原型共享)。

原型式继承并没有使用严格意义上的构造函数,而是借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。

当然,这种方式,包含引用类型值的属性时钟会共享相应的值。

//原型式继承
function object(o) {
function F() {}
F.prototype = o;
return new F();
} var father = {
name: 'try',
colors: ['red']
} //ECMAScript规范了原型式继承
var son1 = Object.create(father);
son1.name = 'rr';
son1.colors.push('yellow');
console.log(son1.colors); var son2 = Object.create(father);
console.log(son2.colors);

5、寄生组合式继承

完美的继承方式,重点掌握。寄生+借用构造,解决了之前需要调用两个父类构造函数的问题。

所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。

不必为例指定子类型的原型而调用父类型的构造函数,我们所需要的无非是父类型原型的一个副本而已。

本质上,就是使用寄生式继承来的父类型的原型,然后再将结果指定给子类型的原型。


function object(fa) {
//实际上是实行了一次浅复制
function F() {}; //为了得到fa的原型创造出的临时对象
F.prototype = fa; //获得原型
return new F();
}
function inheritPrototype(son, father) {
var prototype = object(father.prototype); //创建对象
prototype.constructor = son; //构造函数指向要创建的 即增强对象
son.prototype = prototype; //原型继承
} function father(name) {
this.name = name;
this.colors = ['red'];
}
father.prototype.sayName = function() {
console.log(this.name);
}
function son(name,age) {
father.call(this, name);
this.age = age;
}
inheritPrototype(son,father); var tmp1 = new son('try',19);
tmp1.colors.unshift('yellow');
var tmp2 = new son('tt',10);
console.log(tmp2.colors); //'red'
tmp2.sayName(); //tt

属性继承代码是SuperType.call(this,name);

原型继承代码是inheritPrototype(son,father);

参考《JavaScript高级程序设计第3版》。

JavaScript几种继承方式的总结的更多相关文章

  1. JavaScript之四种继承方式讲解

    在Javascript中,所有开发者定义的类都可以作为基类,但出于安全性考虑,本地类和宿主类不能作为基类,这样可以防止公用访问编译过的浏览器级的代码,因为这些代码可以被用于恶意攻击. 选定基类后,就可 ...

  2. JavaScript几种继承方式

    我们先构建一个Person的构造函数 function Person(name) { this.name=name; } Person.prototype.sayHi=function () { co ...

  3. JavaScript五种继承方式详解

    本文抄袭仅供学习http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html 一. 构造函数绑定 ...

  4. Javascript的四种继承方式

    在Javascript中,所有开发者定义的类都可以作为基类,但出于安全性考虑,本地类和宿主类不能作为基类,这样可以防止公用访问编译过的浏览器级的代码,因为这些代码可以被用于恶意攻击. 选定基类后,就可 ...

  5. JavaScript的3种继承方式

    JavaScript的继承方式有多种,这里列举3种,分别是原型继承.类继承以及混合继承. 1.原型继承 优点:既继承了父类的模板,又继承了父类的原型对象: 缺点:不是子类实例传参,而是需要通过父类实例 ...

  6. JavaScript 的对象继承方式,有几种写法?

    JavaScript 的对象继承方式,有几种写法? 一.对象冒充 其原理如下:构造函数使用 this 关键字给所有属性和方法赋值(即采用类声明的构造函数方式).因为构造函数只是一个函数,所以可使 Pa ...

  7. 架构师JavaScript 的对象继承方式,有几种程序写法?

    架构师JavaScript 的对象继承方式,有几种程序写法?   一.对象冒充 其原理如下:构造函数使用 this 关键字给所有属性和方法赋值(即采用类声明的构造函数方式).因为构造函数只是一个函数, ...

  8. 【设计模式+原型理解】第三章:javascript五种继承父类方式

    [前言] 我们都知道,面向对象(类)的三大特征:封装.继承.多态 继承:子类继承父类的私有属性和公有方法 封装:把相同的代码写在一个函数中 多态: ->重载:JS严格意义上是没有重载,但可以通过 ...

  9. 都0202年了,你还不知道javascript有几种继承方式?

    前言     当面试官问你:你了解js哪些继承方式?es6的class继承是如何实现的?你心中有很清晰的答案吗?如果没有的话,可以通过阅读本文,帮助你更深刻地理解js的所有继承方式.       js ...

随机推荐

  1. MATLAB矩阵的表示

    矩阵是matlab中最基本的数据对象. l  矩阵的建立 l  冒号表达式 l  结构矩阵和单元矩阵 1.矩阵的建立 (1)利用直接输入法建立矩阵:将矩阵的元素用中括号括起来,按矩阵行的顺序输入各元素 ...

  2. 2020年python开发微信小程序,公众号,手机购物商城APP

    2020年最新的技术全栈,手机短信注册登陆等运用, 精准定位用户 支付宝支付 以及前后端从0到大神的全部精解 2020年最新的技术全栈,手机短信注册登陆等运用, 精准定位用户 支付宝支付 以及前后端从 ...

  3. Redis 学习笔记(一) 字符串 SDS

    SDS 简单动态字符串. SDS的结构: struct sdshdr{ int len;//记录BUF数组中已使用字节的数量 ,等于SDS所八寸字符串的长度 int free;//记录BUF数组中未使 ...

  4. 【Hadoop离线基础总结】linux基础增强

    linux基础增强 查找命令 grep命令  (print lines matching a pattern) 概述: grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打 ...

  5. DoNet:浅淡对delegate的理解

    1 前言 C#的相关文档,MSDN上其实已经很详细了,关于delegate的使用可以参 考MSDN上的文档https://msdn.microsoft.com/zh-cn/library/900fyy ...

  6. [hdu4628 Pieces]二进制子状态,DP

    题意:给一个长度为16的字符串,每次从里面删掉一个回文序列,求最少需要几次才能删掉所有字符 思路:二进制表示每个字符的状态,那么从1个状态到另一个状态有两种转移方式,一是枚举所有合法的回文子序列,判断 ...

  7. vue面试常遇到的面试题

    最近面试了好几家公司,总结一下经常被问到的面试题. 首先呢,一开始先来一个自我介绍,没啥好说的. 接下来就是考验你vue技术的问题了 一些常见的面试题 vue的生命周期 一共有八个阶段,分别为创建前后 ...

  8. Ubuntu:Tkinter无法导入

    最近想写个GUI小程序,所以就使用了python内置的Tkinter包,但是导入时竟然提示没有这个包? 使用命令搜索了下: sudo apt search python3-tk ,显示已经安装了.又重 ...

  9. shrine

    0x01 import flask import os app = flask.Flask(__name__) app.config['FLAG'] = os.environ.pop('FLAG') ...

  10. PAT 1028 List Sorting (25分) 用char[],不要用string

    题目 Excel can sort records according to any column. Now you are supposed to imitate this function. In ...