Javascript语言的继承机制,它没有"子类"和"父类"的概念,也没有"类"(class)和"实例"(instance)的区分,全靠一种很奇特的"原型链"(prototype chain)模式,来实现继承。这部分知识也是JavaScript里的核心重点之一,同时也是一个难点。本文先给出了ES5最经典的寄生组合式继承图的详细描述,然后给出了其实现代码,可以配合该图来加深理解。

1. ES5最经典的寄生组合式继承图

  • 注意:如果A.prototype没有constructor,只要B.prototype的原型对象是A.prototype,则b instance of A就为true

2. ES5和ES6的继承

//ES5继承
function Super(name){
this.name=name
this.colors=[1,2,3]
}
Super.prototype.sayName=function(){
alert(this.name)
}
function Sub(name,age){
Super.call(this,name)//显式传入this作为显示调用者调用父类构造函数
this.age=age
}
Sub.prototype=Object.create(Super.prototype,{
constructor:{
value:Sub
}
})//避免调用父类的构造函数
Sub.prototype.sayAge=function(){
alert(this.age)
}
//ES6继承
class Super{
constructor(name){
this.name=name
}
sayName(){
alert(this.name)
}
static haha(){
alert(this.hahatext)//Super函数对象的静态属性
}
}
Super.hahatext="dingxu1"
class Sub extends Super{
constructor(name,age){
super(name)//先实例化父构造函数,在更改this的指向,super()之后才有了this!
this.age=age
}
sayAge(){
alert(this.age)
}
}
Sub.hahatext="dingxu2"
Super.haha()//dingxu1
Sub.haha()//dingxu2
/***********************************************/
Sub.__proto__ === Super // true 作为一个对象,子类(Sub)的原型(__proto__属性)是父类(Super)
Sub.prototype.__proto__ === B.prototype // true 作为一个构造函数,子类(Sub)的原型对象(prototype属性)是父类的原型对象(prototype属性)的实例。
  • ES5 是先新建子类的实例对象this,再将父类的属性添加到子类上,由于父类的内部属性无法获取,导致无法继承原生的构造函数。比如,Array构造函数有一个内部属性[[DefineOwnProperty]],用来定义新属性时,更新length属性,这个内部属性无法在子类获取,导致子类的length属性行为不正常。
  • ES6 允许继承原生构造函数定义子类,因为 ES6 是先新建父类的实例对象this,然后再用子类的构造函数修饰this,使得父类的所有行为都可以继承。下面是一个继承Array的例子。
class MyArray extends Array{
constructor(...args){
super(...args)
}
}
var arr=new MyArray()
arr[0]=12
arr.length
arr.length=0
arr[0]

extends关键字不仅可以用来继承类,还可以用来继承原生的构造函数。因此可以在原生数据结构的基础上,定义自己的数据结构。

class VersionedArray extends Array {
constructor() {
super();
this.history = [[]];
}
commit() {
this.history.push(this.slice());
}
revert() {
this.splice(0, this.length, ...this.history[this.history.length - 1]);
}
} var x = new VersionedArray(); x.push(1);
x.push(2);
x // [1, 2]
x.history // [[]] x.commit();
x.history // [[], [1, 2]] x.push(3);
x // [1, 2, 3]
x.history // [[], [1, 2]] x.revert();
x // [1, 2]

注意,继承Object的子类,有一个行为差异。

class NewObj extends Object{
constructor(){
super(...arguments);
}
}
var o = new NewObj({attr: true});
o.attr === true // false

上面代码中,NewObj继承了Object,但是无法通过super方法向父类Object传参。这是因为 ES6 改变了Object构造函数的行为,一旦发现Object方法不是通过new Object()这种形式调用,ES6 规定Object构造函数会忽略参数。

Javascript的原型链与继承的更多相关文章

  1. JavaScript使用原型链实现继承

    JavaScript实现继承的思想: 一句话总结,让子类的原型等于父类的实例. 详细来说,其实利用了原型的性质即在JavaScript中所有被实例化对象具有相同的原型属性和方法,每一个被实例化对象的原 ...

  2. 三张图搞懂JavaScript的原型对象与原型链 / js继承,各种继承的优缺点(原型链继承,组合继承,寄生组合继承)

    摘自:https://www.cnblogs.com/shuiyi/p/5305435.html 对于新人来说,JavaScript的原型是一个很让人头疼的事情,一来prototype容易与__pro ...

  3. 深入浅出JavaScript之原型链&继承

    Javascript语言的继承机制,它没有"子类"和"父类"的概念,也没有"类"(class)和"实例"(instanc ...

  4. JavaScript原型链与继承

    最近学习了<Javascript高级程序设计>面向对象部分,结合书中的例子总结一下原型链和继承部分的内容. 创建对象 在Js当中没有类这个概念,当我们想要创建具有相同属性的对象的时候,有如 ...

  5. 《JAVASCRIPT高级程序设计》根植于原型链的继承

    继承是面向对象的语言中,一个最为津津乐道并乐此不疲的话题之一.JAVASCRIPT中的继承,主要是依靠原型链来实现的.上一篇文章介绍过,JAVASCRIPT中,每一个对象都有一个prototype属性 ...

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

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

  7. JavaScript中的原型链和继承

    理解原型链 在 JavaScript 的世界中,函数是一等公民. 上面这句话在很多地方都看到过.用我自己的话来理解就是:函数既当爹又当妈."当爹"是因为我们用函数去处理各种&quo ...

  8. JavaScript原型链和继承

    1.概念 JavaScript并不提供一个class的实现,在ES6中提供class关键字,但是这个只是一个语法糖,JavaScript仍然是基于原型的.JavaScript只有一种结构:对象.每个对 ...

  9. JavaScript的原型链继承__propt__、prototype、constructor的理解、以及他们之间相互的关系。

    回想自己已经工作了有一段时间了,但是自己对JavaScript的原型链.和继承的理解能力没有到位,最近他们彻底的整理并且复习了一遍. 本案例中部分文案来自网络和书籍,如有侵权请联系我,我只是把我的理解 ...

随机推荐

  1. vue quill使用&quill 自定义图片上传&自定义mp4 更换标签

    pluins 创建quill 目录 创建文件video.js import { Quill } from 'vue-quill-editor' // 源码中是import直接倒入,这里要用Quill. ...

  2. Codeforces Round #597 (Div. 2) B. Restricted RPS

    链接: https://codeforces.com/contest/1245/problem/B 题意: Let n be a positive integer. Let a,b,c be nonn ...

  3. 02_View

    1.View 1.基于类的视图 Class-based Views REST framework提供APIView是Django的View的子类 发送到View的Request请求:是REST fra ...

  4. ModelAndView返回Json格式的数据

    第一种方式: 1.自定义类JacksonUtil.java,类中实现tojson方法(即将数据转成json类型): 2.自定义类JsonView 继承 AbstractView 3.xml中配置bea ...

  5. 22 | MySQL有哪些“饮鸩止渴”提高性能的方法?

    不知道你在实际运维过程中有没有碰到这样的情景:业务高峰期,生产环境的MySQL压力太大,没法正常响应,需要短期内.临时性地提升一些性能. 我以前做业务护航的时候,就偶尔会碰上这种场景.用户的开发负责人 ...

  6. react的登录逻辑

    https://blog.csdn.net/qq_36822018/article/details/83028661(先看看这个 https://blog.csdn.net/weixin_342681 ...

  7. Gym - 101981E 思维

    Gym - 101981EEva and Euro coins 题意:给你两个长度皆为n的01串s和t,能做的操作是把连续k个相同的字符反转过来,问s串能不能变成t串. 一开始把相同的漏看了,便以为是 ...

  8. CentOS7安装Airflow

    实验环境: centos7python3.6 安装配置: 1.看看是否有gcc,没有的话需要进行安装: yum install gcc  (后续安装airflow如果不成功,可以再次执行,它会更新包) ...

  9. [bzoj 5143][Ynoi 2018]五彩斑斓的世界

    传送门 Descroption 给了你一个长为n的序列a,有m次操作 1.把区间[l,r]中大于x的数减去x 2.查询区间[l,r]中x的出现次数 Solution 分块 对于每个块,我们都分别维护: ...

  10. Docker网络原则入门:EXPOSE,-p,-P,-link

    如果你已经构建了一些多容器的应用程序,那么肯定需要定义一些网络规则来设置容器间的通信.有多种方式可以实现:可以通过--expose参数在运行时暴露端口,或者在Dockerfile里使用EXPOSE指令 ...