博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
js面向对象浅谈(三)
阅读量:5745 次
发布时间:2019-06-18

本文共 2995 字,大约阅读时间需要 9 分钟。

继承

继承是面向对象语言中特别重要的概念,js的继承主要是靠原型链实现的。

原型链!!!

看到我给标题打了三个叹号吗,这里真的很重要!这里真的很重要!这里真的很重要!js描述了原型链的概念,并将原型链做为实现继承的主要方法,其基本思想是让一个引用类型继承另一个引用类型的属性和方法。看代码

function SuperType() {    this.property = true;}SuperType.prototype.getSuperValue = function () {    return this.property;}function SubType () {    this.Subproperty = false;}SubType.prototype = new SuperType();SuperType.prototype.getSubValue = function () {    return this.subproperty;}var instance = new SubType();console.log(instance.getSuperValue())

下面继续上我的灵魂画作:

clipboard.png

话不多说,原理都在图里,相信聪明的你们早就懂了。在上面的代码中,我们没有使用SubType默认提供的原型,而是给它换了一个新原型。这个原型是父类的实例,新原型具有全部属性和方法,现在也存在于子类的原型中了。

通过原型链,本质上扩展了原型搜索机制。在instance.getSuperValue()调用会经历三个搜索步骤

  1. 搜索实例

  2. 搜索原型对象

  3. 搜索父类原型对象

一环一环向上搜索直到原型链末端才会停下来。但是我们子类上的valueOf这些方法是哪里来的呢?父类并没有显示声明这些方法啊下面继续上图。

clipboard.png

SubType继承了SuperType,SuperType继承了Object,当调用instance.valueOf()方法时,实际上调用的是保存在Object.prototype中的方法。

原型链的问题

原型链这么强大,同样也会造成问题。最主要的问题来自于包含引用类型的原型。引用类型的原型属性会被虽有实例共享,在通过原型来实现继承时,原型会变成另一个类型的实例,原先的实例属性也就顺理成章变成来现在的原型属性。

function SuperType () {    this.colors = ['red', 'blue', 'green'];}function SubType () {    }SubType.prototype = new SuperType();var instance1 = new SubType();instance1.colors.push('black');console.log(instance1.colors)var instance2 = new SubType();console.log(instance2.colors)

还有一个问题,就是不能在创建子类性时,像父类型的构造函数传递参数。所以我们一般很少单独使用原型链。

借用构造函数

function SuperType () {    this.colors = ['red', 'blue', 'green'];}function SubType () {    // 继承了 SuperType    SuperType.call(this);}var instance1 = new SubType();instance1.colors.push('black');console.log(instance1.colors);var instance2 = new SubType();console.log(instance2.colors);

也可以传递参数

function SuperType (name) {    this.name = name;}function SubType () {    // 继承了 SuperType    SuperType.call(this, '李小花');}var instance1 = new SubType();console.log(instance1.name)但是这样问题也很明显,方法只能定义在构造函数中定义,定义在原型上的方法无法继承。借用构造函数的技术也很少使用。

组合继承

将原型链和借用构造函数组合到一起,发挥两者之长的一张继承模式,下面来看个例子。
function SuperType (name) {    this.name = name;}SuperType.prototype.sayName = function() {    console.log(this.name)};function SubType (name, age) {    // 继承了 SuperType    SuperType.call(this, name);    this.age = age;}SubType.prototype = new SuperType();var instance1 = new SubType();console.log(instance1.name)

组合继承是 js最常用的继承模式。

寄生组合式继承

组合继承是最常用的继承模式,但也不是没有缺点。组合继承最大的问题是无论在什么情况下,都会调用两次父类型构造函数。

function SuperType (name) {    this.name = name;}SuperType.prototype.sayName = function() {    console.log(this.name)};function SubType (name, age) {    // 继承了 SuperType    SuperType.call(this, name);  //第二次调用    this.age = age;}SubType.prototype = new SuperType();  // 第一次调用var instance1 = new SubType();console.log(instance1.name)

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

function SuperType (name) {    this.name = name;    this.color = ['red', 'blue', 'green'];}SuperType.prototype.sayName = function() {    console.log(this.name);};function SubType (name, age) {    SuperType.call(this, name);    this.age = age;}SubType.prototype = Object.create(SuperType.prototype);SubType.prototype.constructor = SubType

转载地址:http://qtazx.baihongyu.com/

你可能感兴趣的文章
python读excel写入mysql小工具
查看>>
如何学习区块链
查看>>
搜索问题的办法
查看>>
微信分销系统商城营销5大重点
查看>>
求职准备 - 收藏集 - 掘金
查看>>
htm5新特性(转)
查看>>
Linux-Centos启动流程
查看>>
php 设计模式
查看>>
后端技术精选 - 收藏集 - 掘金
查看>>
Laravel 服务容器
查看>>
mac安装kubernetes并运行echoserver
查看>>
多页架构的前后端分离方案(webpack+express)
查看>>
算法(第4版) Chapter 1
查看>>
前端技术选型的遗憾和经验教训
查看>>
“亲切照料”下的领域驱动设计
查看>>
SRE工程师到底是做什么的?
查看>>
解读:Red Hat为什么收购Ansible
查看>>
Ossim下的安全合规管理
查看>>
DelphiWebMVC框架下BPL热部署实现
查看>>
C++与MySQL的冲突
查看>>