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. D. Ehab the Xorcist(纯构造方法)

    \(如果觉得下面难以理解,可以去这里看一种较为简单的解法\):saf \(这个题嘛,首先要明确异或的性质:相同为0,不同为1.\) \(举个例子,我们来构造u=15和v=127的情况\) \(注意到, ...

  2. HDU1300Pearls

    传送门 描述: 有几种不同的珍珠.每种珍珠都有它的单价.当然质量高的珍珠价格一定也是高的. 为了避免买家只买1个珍珠.就要求不论是买了多少个珍珠都是需要在购买数量上加10.之后乘上单价. 例如:买5个 ...

  3. D. Mysterious Present DAG dp

    https://codeforces.com/problemset/problem/4/D 这个题目比较简单,就是一个DAG模型,这个可以看看紫书学习一下, 我这次是用dp来写的,用记忆化搜索也许更好 ...

  4. spring的bean的属性注入

    一.设置注入 设置注入要求: 要求属性在实体类中必须有getter 和setter方法,然后在spring的工厂中就可以使用property标签进行设值注入. 二.构造注入 通过类的构造方法的方式注入 ...

  5. Spring源码阅读 之 bean的注册

    在前面我们已经学习了配置的加载,读取,解析.现在我们已经能够将一份配置转变成对应的一个个beandefinition了,我们知道Spring是一个IOC的容器,那么我们如何将这个一个个beandefi ...

  6. spring学习笔记(三)我对AOP理解

    首先我们要知道AOP是什么?AOP全称Aspect OrientedProgramming,即面向切面编程.在这里我不想去说什么是切面,什么是切点,什么是通知等等,相关博客很多,如果大家想知道可以自己 ...

  7. 74LS 系列 名称解释

    摘自:http://blog.sina.com.cn/s/blog_502ffce50100j9db.html -------------------------------------------- ...

  8. [CodeForces 344D Alternating Current]栈

    题意:两根导线绕在一起,问能不能拉成两条平行线,只能向两端拉不能绕 思路:从左至右,对+-号分别进行配对,遇到连续的两个“+”或连续的两个“-”即可消掉,最后如果全部能消掉则能拉成平行线.拿两根线绕一 ...

  9. Struts2 为什么被淘汰?自己作死!

    Struts2 那些年可谓是风光无限啊,Struts2 + Spring + Hibernate 三大框架一起组成了 "SSH"----牛逼哄哄的 Java Web 框架三剑客. ...

  10. zsy后台管理系统-架构设计

    Zsy框架总体架构设计 1.Mysql数据库,存储所有表的数据. 2.Zsy-基础项目(Zsy-Model,Zsy-Dao,Zsy-Service,Zsy-Web),基于SSM框架.项目功能包含基本的 ...