继承是OO语言中一个最为人津津乐道的概念,也是初接触Javascript的初学者难理解的概念=。=继承主要分为两种:一种是接口继承,另一种是实现继承。而在ECMAScript中只支持实现继承,所以我们今天来讨论讨论实现继承。实现继承就是继承实际的方法,主要依靠原型链来实现。讲到这里我们就需要讨论讨论什么是原型链。

1、什么是原型

  要理解原型链我们首先要知道什么是原型。我们知道每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,这个对象包含所有实例共享的属性和方法。所以我个人觉得可以这么简单的理解:原型就是prototype属性。

  同时prototype属性有自己的prototype对象,而pototype对象肯定也有自己的constuct属性,construct属性有自己的constuctor对象,神奇的事情要发生了,这最后一个constructor对象就是我们构造出来的function函数本身!

2、关于prototype和_proto_

  (1).每个对象都具有一个名为__proto__的属性;

  (2).每个构造函数(构造函数标准为大写开头,如Function(),Object()等等JS中自带的构造函数,以及自己创建的)都具有一个名为prototype的方法(注意:既然是方法,那么就是一个对象(JS中函数同样是对象),所以prototype同样带有__proto__属性);

  (3).每个对象的__proto__属性指向自身构造函数的prototype;

  所以在大多数情况下我们可以这么认为:_proto_===constructor.prototype(某些情况除外,比如:通过Object.create()创建的对象不适用此等式)

3、原型链

  讲到这,到底什么是原型链呢?其实已经很明了了。由于每个对象都有_proto_属性,而在Javascript中万物皆对象,所以最终会形成一条由_proto_连起来的链条,递归访问最终会到头,最终的值为NULL。那么这条链条就是原型链。

  当Javascript引擎查找对象的属性时,先查找对象本身是否存在该属性,如果不存在,那么会在原型链上逐级查找。(但不会查找自身的prototype)

4、继承

  一、原型链式继承

    实现原型链继承有一种基础模式,代码如下:

function SuperType(){this.property=ture;
}SuperType.prototype.getSuperValue=function(){  return this.prototype;};function SubType(){  this.subproperty=false;}SubType.prototype=new SubType();//继承了SuperTypeSubType.prototype.getSubValue=function(){  return this.subproperty;};var instance=new SubType();alert(instance.getSuperValue());//true

 基础原型链继承虽然简单但是它有两个问题:1、在通过原型链继承时,原型实际上会变成另一个类型的实例。于是,原先的实例属性也就顺理成章地变成了现在的原型属性了。2、在创建子类型的实例时,不能向超类型的构造函数中传递函数。

  二、借用构造函数继承

  在子类型构造函数的内部调用超类构造函数,通过使用call()和apply()方法可以在新创建的对象上执行构造函数。

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

  借用构造函数的问题:放大都在构造函数中,因此函数的复用就无从谈起。而且,在超类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。

  三、组合继承

function Super(){// 只在此处声明基本属性和引用属性this.val = 1;this.arr = [1];
}
//  在此处声明函数
Super.prototype.fun1 = function(){};
Super.prototype.fun2 = function(){};
//Super.prototype.fun3...
function Sub(){Super.call(this);   // 核心// ...
}
Sub.prototype = new Super();    // 核心var sub1 = new Sub(1);
var sub2 = new Sub(2);
alert(sub1.fun === sub2.fun);   // true

  为了解决借用构造函数继承的问题,组合继承应运而生。

  组合继承把实例函数都放在原型对象上,以实现函数复用。同时还要保留借用构造函数方式的优点,通过Super.call(this);继承父类的基本属性和引用属性并保留能传参的优点;通过Sub.prototype = new Super();继承父类函数,实现函数复用。

  组合继承避免了原型链继承和借用构造函数继承的缺点,融合了他们的优点:不存在引用属性共享问题,可传参,函数可复用。因此成为Javascript中最常见的继承模式。

  缺点:组合集成的最大问题是在无论什么情况下都会调用两次超类型构造函数。

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);//第一次调用SuperType()this.age=age
}
SubType.prototype=new SuperType();//第二次调用SuperType()
SubType.prototype.constructor=function(){alert(this.age);
};

  

  四、寄生式组合继承

    既然组合继承也有不足之处,那当然就需要弥补,于是就出现了寄生式组合继承。

寄生式组合继承的基本模式如下:

function inheritPrototype(subType,superType){var prototype=Object(superType.prototype);//创建对象prototypr.constructor=subType;//增强对象  弥补因重写原型失去的默认的constructor属性  subType.prototype=prototype;//指定对象 将新创建的对象赋值给子类型的原型}

这个示例中的inheritPrototype()函数实现了组合继承的最简单形式。我们可以调用inheritPrototype()函数区替换前面例子中的子类型原型赋值函数:

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);//第一次调用SuperType()this.age=age
}
inheritPrototype(Subtype,Supertype);
SubType.prototype.sayAge=function(){alert(this.age);
};

  这个例子的搞笑体现在只调用了一次Supertype构造函数,避免了在SubType.prototype上创建的不必要、多余的属性。与此同时还能保持原型链的不变;因此,还能正常使用instanceof和isPrototypeOf()。所以现在寄生式组合继承是最理想的继承方式。

PS:关于原型式继承和寄生式继承在这里就不多做解释了。大家可以自己去查相关的资料,不太推荐使用(个人观点)。

转载于:https://www.cnblogs.com/hsc958/p/7139186.html

对Javascript的原型,原型链和继承的个人理解相关推荐

  1. 对Javascript 类、原型链、继承的理解

    一.序言   和其他面向对象的语言(如Java)不同,Javascript语言对类的实现和继承的实现没有标准的定义,而是将这些交给了程序员,让程序员更加灵活地(当然刚开始也更加头疼)去定义类,实现继承 ...

  2. JavaScript 原型链和继承面试题

    JavaScript 原型链和继承问题 JavaScript 中没有类的概念的,主要通过原型链来实现继承.通常情况下,继承意味着复制操作,然而 JavaScript默认并不会复制对象的属性,相反,Ja ...

  3. 一篇JavaScript技术栈带你了解继承和原型链

    作者 | Jeskson 来源 | 达达前端小酒馆 1 在学习JavaScript中,我们知道它是一种灵活的语言,具有面向对象,函数式风格的编程模式,面向对象具有两点要记住,三大特性,六大原则. 那么 ...

  4. JavaScript:原型链、继承

    1.理解原型对象 我们先使用构造函数创建一个对象: function Person() { } var person = new Person(); person.name = 'Kevin'; co ...

  5. JavaScript (四) ——构造函数原型 , 原型链 和继承

    原型 所有引用类型都有一个_proto_属性, 属性值是对象 所有函数都有一个prototype属性 , 属性值是一个对象 所有引用类型的_proto_属性 , 都指向其构造函数的prototype ...

  6. JavaScript原型链实现继承

    js 继承 原型链 默认的原型 确定原型和实例的关系 谨慎定义方法 原型链的问题 借用构造函数 组合继承 最常用的继承模式 原型式继承 寄生式继承 寄生组合式继承 是引用类型最理想的继承范式 学习记录 ...

  7. 【JavaScript】面向对象、原型和原型链、继承

    1. *****面向对象: OOP 什么是对象: 内存中集中存储多个数据或函数的存储空间,再起一个名字. 对象是程序中描述现实中一个具体事物的属性和功能的结构 什么是面向对象: 程序中都是先用对象描述 ...

  8. (转)【javascript基础】原型与原型链

    原文地址:http://www.cnblogs.com/allenxing/p/3527654.html 前言 原型是什么 理解原型对象 原型对象 isPrototypeOf hasOwnProper ...

  9. JavaScript中的原型(prototype)与继承

    在JavaScript中,原型是用来模仿其他「类」语言继承机制的基础.原型并不复杂,原型只是一个对象. 一.原型对象 1.1 什么是原型对象 每当我们创建了一个函数后,这个函数就拥有了一个protot ...

  10. JavaScript对象、原型、原型链知识总结思维导图

    这个思维导图是我对Object,原型,原型链等知识的总结,主要参考高程一书第六章,写完才发现这么多,以后可能会进行精简.内容可能会出现差错,欢迎批评指正.下载==>Github ECMAScri ...

最新文章

  1. [unreal4入门系列之十二] 在UE4中创建非玩家角色(NPC)
  2. 【译】Spring 官方教程:Spring Security 架构
  3. php7.2 swoole_loader,用什么方法可以让swoolec-loader支持php7.3?
  4. Android压缩文件(压缩目录)
  5. java序列化的方法_【Java常见序列化与反序列方法总结】
  6. HDU2010 水仙花数【进制+入门】
  7. python画围棋棋盘_python3 turtle 画围棋棋盘
  8. html自动触发双击事件,js主动触发单击事件
  9. qt实现windows系统下录屏功能
  10. doctrine-orm基础(单用doctrine避坑指南)
  11. 第一课 让人拍案叫绝的创意都是如何诞生的?
  12. 如何用laragon框架运行php文件
  13. tree.js 酷炫的效果,人脸识别签到思路,html5 3D微信头像自动抽奖代码
  14. SPAMS Matlab 安装
  15. 计算机控制系统康波答案,计算机控制系统部分习题参考答案1
  16. Android 平台代号、版本、API 级别和 NDK 版本对照表
  17. 个人网站设计-Stigma
  18. 以可视化的方式来打开大数据,tableau是如何连接到Hadoop hive的?
  19. 【博弈论】【第一章】博弈论导论
  20. 马哥linux运维1~14讲笔记+自我知识储备补充

热门文章

  1. java 与 php 区别或异同(整理、整合)
  2. RequestContextHolder 获取 ServletRequest 和 ServletResponse,Spring MVC ModelAndView 数据响应 Response
  3. HTML DOM Image 对象
  4. MySql 5.7.26(MySQL8)安装教程
  5. 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_3-1.整合Mybatis访问数据库和阿里巴巴数据源...
  6. child-selector解释
  7. Backbone.js Wine Cellar 教程
  8. C# 基础-CLR-类型【0】
  9. [转]请不要和陌生女人说话
  10. 最长公共子序列和最长子字符串_python_算法与数据结构