《javascript高级程序设计》笔记:继承
继承和前面两篇文章中的知识非常相关,如果对函数创建原理
和原型链
不熟悉,请猛戳:
《javascript高级程序设计》笔记:创建对象
《javascript高级程序设计》笔记:原型图解
继承,通俗的说,就是将自身不存在的属性或方法,通过某种方式为自己所用
文章分别介绍原型链继承、call/apply继承(借用构造函数继承)、组合继承、原型式继承、寄生式继承、寄生组合式继承
1. 原型链继承
核心:将父类的实例作为子类的原型
function SuperType(){this.property = true;
}
SuperType.prototype.getSuperValue = function(){return this.property;
};function SubType(){this.subproperty = false;
}
// 继承自SuperType
SubType.prototype = new SuperType();SubType.prototype.getSubValue = function (){return this.subproperty;
};var instance = new SubType();
alert(instance.getSuperValue());//true
简单的原型链分析
在《javascript高级程序设计》笔记:创建对象
的文章中,使用原型创建对象会存在多个实例对引用类型的操作会被篡改的问题,在上面同样存在这个问题,如下:
function SuperType(){this.colors = ["red", "blue", "green"];
}
function SubType(){}SubType.prototype = new SuperType();var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"var instance2 = new SubType();
alert(instance2.colors); //"red,blue,green,black"
两个实例对象instance1和instance2的colors属性指向相同,改变一个会影响另一个实例的属性
缺陷:
(1)原型链继承多个实例的引用类型属性指向相同,存在篡改的可能
(2)不能传递参数
2. 借用构造函数继承
核心:使用父类的构造函数来增强子类实例,等同于复制父类的实例给子类(不使用原型)
function SuperType(name){this.name = name;this.colors = ["red", "blue", "green"];
}function SubType(name, age){// 继承自SuperTypeSuperType.call(this, name);this.age = age;
}var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"var instance2 = new SubType();
alert(instance2.colors); //"red,blue,green"alert(instance1.name); // "Nicholas"
alert(instance1.age); // 29
借用构造函数继承的核心就在于SuperType.call(this, name)
,“借调”了SuperType构造函数,这样,SubType的每个实例都会将SuperType中的属性复制一份
缺陷:
(1)只能继承父类的实例属性和方法,不能继承原型属性/方法
(2)无法实现复用,每个子类都有父类实例函数的副本,影响性能
3. 组合继承
核心:结合原型链继承和构造函数继承通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
其背后的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承,这样,既通过在原型上定义方法实现了函数复用,又能保证每个实例都有它自己的属性
function SuperType(name){this.name = name;this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){alert(this.name);
};function SubType(name, age){//继承属性SuperType.call(this, name);this.age = age;
}// 继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){alert(this.age);
};var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"Nicholas";
instance1.sayAge(); //29var instance2 = new SubType("Greg", 27);
alert(instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //27
图解:
缺陷:
父类中的实例属性和方法既存在于子类的实例中,又存在于子类的原型中,不过仅是内存占用,因此,在使用子类创建实例对象时,其原型中会存在两份相同的属性/方法
这个方法是javascript中最常用的继承模式
4. 原型式继承
核心:直接将某个对象直接赋值给构造函数的原型
function object(obj){function F(){}F.prototype = obj;return new F();
}
object()对传入其中的对象执行了一次浅复制
,将F的原型直接指向传入的对象
var person = {name: "Nicholas",friends: ["Shelby", "Court", "Van"]
};var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");alert(person.friends); //"Shelby,Court,Van,Rob,Barbie"
缺点:
(1)原型链继承多个实例的引用类型属性指向相同,存在篡改的可能
(2)无法传递参数
另外,ES5中存在Object.create()
的方法,能够代替上面的object方法
5. 寄生式继承
核心:在原型式继承的基础上,增强对象,返回构造函数
function createAnother(original){ varclone=object(original); // 过调用函数创建一个新对象clone.sayHi = function(){ // 以某种方式增强这个对象alert("hi");};return clone; // 返回对象
}
函数的主要作用是为构造函数新增属性和方法,以增强函数
var person = {name: "Nicholas",friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"
缺点:
(1)原型链继承多个实例的引用类型属性指向相同,存在篡改的可能
(2)无法传递参数
6. 寄生组合式继承
核心:结合借用构造函数传递参数和寄生模式实现继承
function inheritPrototype(subType, superType){var prototype = Object.create(superType.prototype); //创建对象prototype.constructor = subType; // 增强对象subType.prototype = prototype; // 指定对象
}// 父类初始化实例属性和原型属性
function SuperType(name){this.name = name;this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){alert(this.name);
};// 借用构造函数传递增强子类实例属性(支持传参和避免篡改)
function SubType(name, age){SuperType.call(this, name);this.age = age;
}// 将父类原型指向子类
inheritPrototype(SubType, SuperType);// 新增子类原型属性
SubType.prototype.sayAge = function(){alert(this.age);
}var instance1 = new SubType("xyc", 23);
var instance2 = new SubType("lxy", 23);instance1.colors.push("2"); // ["red", "blue", "green", "2"]
instance1.colors.push("3"); // ["red", "blue", "green", "3"]
图解:
寄生组合继承集合了前面几种继承优点,几乎避免了上面继承方式的所有缺陷,是执行效率最高也是应用面最广的,就是实现的过程相对繁琐
参考:
JS继承的实现方式
面向对象的程序设计之继承
MDN——Object.create()
《javascript高级程序设计》笔记:继承相关推荐
- JavaScript高级程序设计笔记01 | 第一章到第四章 | 关键字与保留字 | 数据类型 | 操作符 | 作用域
观前提示:大部分都是书上的内容,个人理解的部分的较少,看我的笔记还不如去看书 第二章 async:可选.表示应该立即下载脚本,但不应妨碍页面中的其他操作,比如下载其他资源或 等待加载其他脚本.只对外部 ...
- javascript高级程序设计--笔记01
概述 JavaScript的实现包含三个部分: 1 核心(ECMAScript) 提供核心语言功能 2 文档对象模型(DOM) 一套提供了访问以及操作网页内容的API 3 浏览器对象模型( ...
- JavaScript高级程序设计笔记 - 第四章 变量 作用域 内存问题
4.1 基本类型和引用类型的值 基本类型: 简单的数据段 引用类型: 指那些可能有多个值构成的对象, 指保存在内存中的对象 4.1.2 复制变量值 除了保存的方式不同之外,在从一个变量向另一个变量复制 ...
- javascript高级程序设计笔记
1.要讲一个值转换成其对应的Boolean类型 ,可以调用转型函数Boolean(). var message="hello world!"; var messageAsBoole ...
- JavaScript高级程序设计笔记 事件冒泡和事件捕获
1.事件冒泡 要理解事件冒泡,就得先知道事件流.事件流描述的是从页面接收事件的顺序,比如如下的代码: <body><div> click me!</div> < ...
- 《javascript高级程序设计》笔记:内存与执行环境
上一篇:<javascript高级程序设计>笔记:继承 近几篇博客都会围绕着图中的知识点展开 由于javascript是一门具有自动垃圾收集机制的编程语言,开发者不必担心内存的分配和回收的 ...
- 《javascript高级程序设计》笔记:原型图解
文章直接从原型图解开始的,如果对一些概念不太清除,可以结合后面几节查看 1. 图解原型链 1.1 "铁三角关系"(重点) function Person() {}; var p = ...
- 《JavaScript高级程序设计》笔记总结
在北京上班的我每天在上下班路上的时间总共是两个半小时,为了充实这两个多小时的时间,我便花了银子换得了下面这个宝贝 本书内容(引用书中前言) 本书提供了JavaScript开发人员必须掌握的内容,全面涵 ...
- JavaScript高级程序设计(读书笔记)(六)
本笔记汇总了作者认为"JavaScript高级程序设计"这本书的前七章知识重点,仅供参考. 第六章 面向对象的程序设计 面向对象(Object-Oriented, OO)的语言有一 ...
- 《JavaScript高级程序设计》读书笔记 【8章~】【持更】
文章目录 上一篇:<JavaScript高级程序设计>读书笔记 [1~7章] 8. BOM 8.1. window对象 窗口位置 窗口大小 打开窗口 间歇调用与超时调用 系统对话框 8.2 ...
最新文章
- Tornado写简易服务器
- oracle恢复某个表的数据库,如何从rman的全备份中恢复一张表?
- 中国科学院大学2014年数学分析高等代数考研试题
- 八千字长文深度解读,迁移学习在强化学习中的应用及最新进展
- vs2012生成的项目,如何在只装有VS2010的电脑上打开
- android之NDK version was not found
- 【冒泡排序】c++实现冒泡排序代码
- DeepFaceLab坑之ffmpeg
- 揭露富爸爸背后真正的秘密
- Qt调用外部程序,启动并从中获取信息——QProcess
- 日系插画学习笔记(三):光影与结构
- 3G到5G,运营商的“失落十年”
- NFM 网络介绍与源码浅析
- FineReport 填报报表数据自定义提交
- 【Creo5.0二次开发参数化】选择装配
- 【实战篇】37 # 如何使用 QCharts 图表库绘制常用数据图表?
- AcWing 844.走迷宫
- USB HUB芯片 FE8.1替代方案
- PL/SQL 入门学习(一)
- 实现原理讲解!我的阿里春招之路分享,灵魂拷问
热门文章
- conda常用命令和基础知识整理
- nowcoder猜想c语言筛子,剑指 Offer 50 道经典算法题视频讲解
- 凸优化第七章统计估计 7.5实验设计
- 最新android APP框架介绍
- Karta:IDA源代码辅助插件
- 搭建springmvc项目遇到的问题
- 能力提升综合题单Part 8.9.3 费用流
- 三个点在同一个半圆的概率_圆形水池中的四只小鸭子出现在同一个半圆中的概率是?...
- r语言上机文本分析与词云绘制_R语言jiebaR包文本中文分词及词云上机练习,小白能做到...
- Nginx配置与安装及发布项目