JS学习笔记——JavaScript继承的6种方法(原型链、借用构造函数、组合、原型式、寄生式、寄生组合式)
JavaScript继承的6种方法
1,原型链继承
2,借用构造函数继承
3,组合继承(原型+借用构造)
4,原型式继承
5,寄生式继承
6,寄生组合式继承
1.原型链继承.
<script type="text/javascript">
function Person(name,sex)
{
this.name=name;
this.sex=sex;
this.friends=['李四'];
this.getName=function(){
alert(this.name);
}
}
Person.prototype.id=1; function Boy(age)
{
this.age=age;
this.getAge=function(){
alert(this.age);
} }
//继承
Boy.prototype=new Person("张三","男"); var boy=new Boy(16); alert(boy.name); //张三
boy.getAge(); //
alert(boy.id); // //属性共享问题
console.log(boy.friends); //李四 var boy2=new Boy(17);
boy2.friends.push('王五'); //修改boy2的friends属性的同时也影响了boy的属性 console.log(boy.friends); //李四 王五 //验证能否使用instanceof 和 isPrototypeof
console.log(boy instanceof Person); //true
console.log(Person.prototype.isPrototypeOf(boy)); //true
</script>
特点:既继承了父类的模板,又继承了父类的原型对象。
缺点:只能在父类设置一些参数,子类不能灵活传参,不符合面向对象的思想,包含引用类型值的属性始终都会共享相应的值。

2.借用构造函数继承
<script type="text/javascript">
//父类
function Person(name,sex)
{
this.name=name;
this.sex=sex;
this.friends=['李四'];
}
Person.prototype.id=1;
//子类
function Boy(name,sex,age)
{ //借用
Person.call(this,name,age); this.age=age;
this.getAge=function(){
alert(this.age);
} } var boy=new Boy("张三","男",16);
alert(boy.name); //张三 boy.getAge(); // alert(boy.id); //undefined 没有继承父类的原型对象 //属性共享问题 ————不会有共享 //验证能否使用instanceof 和 isPrototypeof
console.log(boy instanceof Person); //false
console.log(Person.prototype.isPrototypeOf(boy)); //false
</script>
特点:只继承了父类的模板,不继承父类的原型对象。
缺点:方法都在构造函数中定义,不能做到函数复用。

3.组合继承(原型+借用构造)最常用的继承模式
<script type="text/javascript">
//父类
function Person(name,sex)
{
this.name=name;
this.sex=sex; }
Person.prototype.id=1;
//子类
function Boy(name,sex,age)
{ //借用构造函数 继承父类的模板
Person.call(this,name,age); this.age=age;
this.getAge=function(){
alert(this.age);
} } //不传递参数,继承父类的模板,继承父类的原型对象 id
Boy.prototype=new Person(); var boy=new Boy("张三","男",16);
alert(boy.name); //张三 boy.getAge(); // alert(boy.id); // //属性共享问题 ————除了父类的原型对象,不会有共享 //验证能否使用instanceof 和 isPrototypeof
console.log(boy instanceof Person); //true
console.log(Person.prototype.isPrototypeOf(boy)); //true
</script>
特点:既继承了父类的模板,又继承了父类的原型对象。
缺点:做了3件事,继承了父类两次模板,继承了一次原型对象
原型式继承解决了这个问题

4.原型式继承
<script type="text/javascript">
var person={
name:'张三',
sex:'男',
friends:['李四']
} function object(obj)
{
function F(){} //创建一个空的构造函数
F.prototype=obj; //将传入的对象作为这个构造函数的原型
return new F(); //返回一个新实例 对传入的对象进行了一次浅复制
} var boy=object(person);
//ECMAScript 5 新增了Object.create()方法 与本例 object 方法行为相同
//可改为 Object.create(person); alert(boy.name); //张三 //但是原型式同样存在属性共享的问题
//例如: var girl=object(person);
girl.friends.push('王五'); alert(boy.friends); //李四 王五
alert(girl.friends);//李四 王五 //修改girl中的friends属性 boy 也会受到影响 //无法使用 instanceof 和 isPrototypeof </script>
创造的目的是基于已有的对象创建新的对象,同时还不必因此创建自定义类型。
包含引用类型值的属性始终都会共享相应的值,就像使用原型模式一样。

5.寄生式继承
<script type="text/javascript">
function object(obj)
{
function F(){} //创建一个空的构造函数
F.prototype=obj; //将传入的对象作为这个构造函数的原型
return new F(); //返回一个新实例 对传入的对象进行了一次浅复制
} function Person(person)
{
var clone=object(person);
clone.getSex=function(){
alert(this.sex);
}
return clone;
}
var person={
name:'张三',
sex:'男',
friends:['李四']
}
var boy=Person(person);
boy.getSex(); //男 //属性共享问题————因为传入同一个实例,所以存在共享问题
var boy2=Person(person);
boy2.friends.push('王五'); alert(boy.friends); //李四 王五 //验证能否使用instanceof 和 isPrototypeof
console.log(boy instanceof Person); //false
console.log(Person.prototype.isPrototypeOf(boy)); //false
</script>
与构造函数模式类似,不能做到函数复用会降低效率。
6.寄生组合式继承
<script type="text/javascript">
function object(o)
{
function F(){}
console.log(o);
F.prototype=o;
return new F();
}
function extend(subType,superType)
{
var prototype=object(superType.prototype); //创建父类的一个副本
prototype.constructor=subType; //为创建的副本添加失去默认的构造函数
subType.prototype=prototype; //将新创建的对象赋值给子类的原型
}
function Person(name)
{
this.name=name;
this.friends=['李四'];
}
function Boy(name,sex)
{
Person.call(this,name); //借用构造函数 继承父类的模板
this.sex=sex;
}
extend(Boy,Person); //继承
var boy=new Boy('张三','男');
alert(boy.name); //张三
//属性共享问题————不会存在共享问题
var boy2=new Boy('张三','男');
boy2.friends.push('王五');
alert(boy.friends); //李四
//验证能否使用instanceof 和 isPrototypeof
console.log(boy instanceof Person); //false
console.log(Person.prototype.isPrototypeOf(boy)); //false
</script>
寄生式组合继承解决了组合继承会调用两次父类构造函数,子类最终会包含父类的全部实例属性,父类的属性不是必须的,子类的属性会覆盖父类的属性。
寄生式组合继承只调用一次父类构造函数,原型链能保持不变,因此还能够正常使用instanceof和isPrototypeOf(),YUI的extend方法就使用的是寄生组合继承,是实现基于类型继承的最有效的方式。

JS学习笔记——JavaScript继承的6种方法(原型链、借用构造函数、组合、原型式、寄生式、寄生组合式)的更多相关文章
- [JS学习笔记]Javascript事件阶段:捕获、目标、冒泡
当你在浏览器上点击一个按钮时,点击的事件不仅仅发生在按钮上,同时点击的还有这个按钮的容器元素,甚至也点击了整个页面. 事件流 事件流描述了从页面接收事件的顺序,但在浏览器发展到第四代时,浏览器开发团队 ...
- js对象之间的"继承"的五种方法
今天要介绍的是,对象之间的"继承"的五种方法. 比如,现在有一个"动物"对象的构造函数. function Animal(){ this.species = & ...
- [前端JS学习笔记]JavaScript CallBack
一.概念介绍 CallBack : "回调" . 在spring优秀框架回调无处不在, 回调的运用场景很多, 如 swt事件监听.netty等.它的主要作用是提高程序执行效率, 一 ...
- [前端JS学习笔记]JavaScript 数组
一.JavaScript数组的奇葩 大多数语言会要求数组的元素是同个类型, 但是JavaScript允许数组元素为多种类型. var arr = ["羽毛球", 666, {&qu ...
- javascript继承的6种方法
1原型式继承 简介:对类式继承的封装,过渡对象相当于子类. function inheritObject(o) { //声明过渡函数对象 function F() {} //过渡对象的原型继承父类 F ...
- javascript继承的几种方法
继承是面向对象编程中很重要的概念,在其它面向对象的语言中大都很简单,例如java中有关键词extends来实现 javascript语言在ES6也新增了extends关键词可以实现继承,用法与java ...
- C#学习笔记(12)——三种方法操作XML
说明(2017-7-11 16:56:13): 原文地址: C#中常用的几种读取XML文件的方法 XML文件是一种常用的文件格式,例如WinForm里面的app.config以及Web程序中的web. ...
- JavaScript构造函数+原型创建对象,原型链+借用构造函数模式继承父类练习
虽然经常说是做前端开发的,但常常使用的技术反而是JQuery比较多一点.在JavaScript的使用上相对而言少些.尤其是在创建对象使用原型链继承上面,在项目开发中很少用到.所以今天做个demo练习一 ...
- 一篇文章理解JS继承——原型链/构造函数/组合/原型式/寄生式/寄生组合/Class extends
说实在话,以前我只需要知道"寄生组合继承"是最好的,有个祖传代码模版用就行.最近因为一些事情,几个星期以来一直心心念念想整理出来.本文以<JavaScript高级程序设计&g ...
随机推荐
- 工资不高也要给自己放假 这几款APP估计你用得上
我是这样的一个人,我宁愿工资不高,只要给我足够的假期,那我就满足了.都说上班就是为了赚钱,但如果身体不好,赚再多的钱也是无福享受,所以建议各位,有机会的话,一定要抽出时间去旅游,去放松. 现在我们外出 ...
- DirectFB 之 字体显示(2)
框架 示例代码 /********************************************** * Author: younger.liucn@hotmail.com * File n ...
- 内核初始化优化宏(__init, __devinit)
在内核里经常可以看到__init, __devinit这样的语句,这都是在init.h中定义的宏,gcc在编译时会将被修饰的内容放到这些宏所代表的section. 原文地址:http://blog.c ...
- webpack中dev-server不写contentBase时如何设置可以显示页面并且加载js
今天学习了dev-server这个配置,中间遇到疑惑,我写了contentBase是可以走通,可以再localhost:8080看到页面并且正确加载bundle.js的,但是这个contentBase ...
- 蓝桥杯-四平方和-java
/* (程序头部注释开始) * 程序的版权和版本声明部分 * Copyright (c) 2016, 广州科技贸易职业学院信息工程系学生 * All rights reserved. * 文件名称: ...
- 读入一个自然数n,计算其各位数字之和,用汉语拼音写出和的每一位数字。 输入格式:每个测试输入包含1个测试用例,即给出自然数n的值。这里保证n小于10的100次幂。 输出格式:在一行内输出n的各位数字之和的每一位,拼音数字间有1 空格,但一行中最后一个拼音数字后没有空格。 输入样例: 1234567890987654321123456789 输出样例: yi san wu
这是PAT中的一道练习题 刚开始的时候我想着直接定义正整数n,结果走了很大的弯路,因为题目中要求n小于10的100次幂,即最大的正整数n有100位,而C语言中整型数字最大占8个字节的存储空间,如果按无 ...
- 基于Struts2的SpringMVC入门
1.SpringMVC概述 (1)SpringMVC为表现层提供基础的基于MVC设计理念的优秀Web框架, (2)SpringMVC通过一套mvc的注解,让POJO成为处理请求的控制器,而无需任何接口 ...
- Unity SLua 如何调用Unity中C#方法
1.原理 就是通常在Lua框架中所说的,开放一个C#的web接口,或者叫做在Slua框架中注册函数. 2.作用 在Lua中调用C#中的方法,这个是在做热更新中很常用的一种方法,无论是slua,还是lu ...
- hdu4597 Play Game DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4597 感觉很不错的区间DP,又做了一遍,感觉自己对边界的处理还是很欠缺 代码: #include< ...
- Phaser类详解
Phaser允许并发多阶段任务.Phaser类机制是在每一步结束的位置对线程进行同步,当所有的线程都完成了这一步,才允许执行下一步. 一个Phaser对象有两种状态: 活跃态(Active):当存在参 ...