1、简介

  Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。

  子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。

  在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错。这是因为子类实例的构建,是基于对父类实例加工,只有super方法才能返回父类实例。

2、Object-getPrototypeOf

  Object.getPrototypeOf方法可以用来从子类上获取父类。

Object.getPrototypeOf(ColorPoint) === Point
// true

  因此,可以使用这个方法判断,一个类是否继承了另一个类。

3、super-关键字

  super这个关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。

  第一种情况super作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次super函数。

class A {
constructor() {
console.log(new.target.name);
}
}
class B extends A {
constructor() {
super();
}
}
new A() // A
new B() // B

   注意,super虽然代表了父类A的构造函数,但是返回的是子类B的实例,即super内部的this指的是B,因此super()在这里相当于A.prototype.constructor.call(this)

  上面代码中,new.target指向当前正在执行的函数。可以看到,在super()执行时,它指向的是子类B的构造函数,而不是父类A的构造函数。也就是说,super()内部的this指向的是B

  作为函数时,super()只能用在子类的构造函数之中,用在其他地方就会报错。

class A {}

class B extends A {
m() {
super(); // 报错
}
}

  上面代码中,super()用在B类的m方法之中,就会造成句法错误。

  第二种情况super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。

class Parent {
static myMethod(msg) {
console.log('static', msg);
} myMethod(msg) {
console.log('instance', msg);
}
} class Child extends Parent {
static myMethod(msg) {
super.myMethod(msg);
} myMethod(msg) {
super.myMethod(msg);
}
} Child.myMethod(); // static 1 var child = new Child();
child.myMethod(); // instance 2

  上面代码中,super在静态方法之中指向父类,在普通方法之中指向父类的原型对象。

4、类的-prototype-属性和__proto__属性

  大多数浏览器的 ES5 实现之中,每一个对象都有__proto__属性,指向对应的构造函数的prototype属性。Class 作为构造函数的语法糖,同时有prototype属性和__proto__属性,因此同时存在两条继承链。

(1)子类的__proto__属性,表示构造函数的继承,总是指向父类。

(2)子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性。

class A {
} class B extends A {
} B.__proto__ === A // true
B.prototype.__proto__ === A.prototype // true

  上面代码中,子类B__proto__属性指向父类A,子类Bprototype属性的__proto__属性指向父类Aprototype属性。

  子类实例的__proto__属性的__proto__属性,指向父类实例的__proto__属性。也就是说,子类的原型的原型,是父类的原型

var p1 = new Point(, );
var p2 = new ColorPoint(, , 'red'); p2.__proto__ === p1.__proto__ // false
p2.__proto__.__proto__ === p1.__proto__ // true

  上面代码中,ColorPoint继承了Point,导致前者原型的原型是后者的原型。

  因此,通过子类实例的__proto__.__proto__属性,可以修改父类实例的行为。

p2.__proto__.__proto__.printName = function () {
console.log('Ha');
}; p1.printName() // "Ha"

  上面代码在ColorPoint的实例p2上向Point类添加方法,结果影响到了Point的实例p1

  

5、原生构造函数的继承 

  原生构造函数是指语言内置的构造函数,通常用来生成数据结构。ECMAScript 的原生构造函数大致有下面这些。

  • Boolean()
  • Number()
  • String()
  • Array()
  • Date()
  • Function()
  • RegExp()
  • Error()
  • Object()

  以前,这些原生构造函数是无法继承的,比如,不能自己定义一个Array的子类。

  ES6 允许继承原生构造函数定义子类,因为 ES6 是先新建父类的实例对象this,然后再用子类的构造函数修饰this,使得父类的所有行为都可以继承。

  意味着,ES6 可以自定义原生数据结构(比如ArrayString等)的子类,这是 ES5 无法做到的。

  因此可以在原生数据结构的基础上,定义自己的数据结构。

From: http://es6.ruanyifeng.com/#docs/class-extends

ES6 class的继承-学习笔记的更多相关文章

  1. 【09-23】js原型继承学习笔记

    js原型继承学习笔记 function funcA(){ this.a="prototype a"; } var b=new funcA(); b.a="object a ...

  2. ES6中Map数据结构学习笔记

    很多东西就是要细细的品读然后做点读书笔记,心理才会踏实- Javascript对象本质上就是键值对的集合(Hash结构),但是键只能是字符串,这有一定的限制. 1234 var d = {}var e ...

  3. 【转载】Javascript原型继承-学习笔记

    阮一峰这篇文章写的很好 http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javas ...

  4. JavaScript 类型、原型与继承学习笔记

    目录 一.概览 二.数据类型 1. JavaScript中的数据类型 2. 什么是基本类型(Primitive Data Type) 2.1 概念 2.2 七个基本类型 2.3 基本类型封装对象 3. ...

  5. JavaScript继承学习笔记

    JavaScript作为一个面向对象语言(JS是基于对象的),可以实现继承是必不可少的,但是由于本身并没有类的概念,所以不会像真正的面向对象编程语言通过类实现继承,但可以通过其他方法实现继承.(jav ...

  6. c++ 继承学习笔记

    三大继承原则(由我杜撰) 基类的私有成员被继承后不可见(优先级最高) 公有继承不改变基类成员属性 保护继承(私有继承)把基类成员变为保护成员(私有成员)

  7. ES6/7 异步编程学习笔记

    前言 在ES6的异步函数出现之前,Js实现异步编程只有settimeout.事件监听.回调函数等几种方法 settTmeout 这种方法常用于定时器与动画的功能,因为其本质上其实是浏览器的WebAPI ...

  8. ES6基础教程一 学习笔记

    一.变量的声明 1.var 声明全局变量 在ES6中var用来声明全局变量. 2.let 声明局部变量 3.const 声明常量 二.变量的解构赋值 //1.数组赋值 let [a,b,c]=[1,2 ...

  9. 《C++ Primer Plus》14.2 私有继承 学习笔记

    C++(除了成员变量之外)还有另一种实现has-a关系的途径——私有继承.使用私有继承,基类的公有成员和保护成员都将成为派生类的私有成员.(如果使用保护继承,基类的公有成员和保护成员都将称为派生类的保 ...

  10. es6字符串的扩展学习笔记

    1. 传统上,JavaScript只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中.ES6又提供了三种新方法. includes():返回布尔值,表示是否找到了参数字符串. st ...

随机推荐

  1. leetcode-algorithms-8 String to Integer (atoi)

    leetcode-algorithms-8 String to Integer (atoi) Implement atoi which converts a string to an integer. ...

  2. Redis(window版本)安装及使用

    1.打开redis官网http://redis.io/点击Download 2.往下拉,找到Windows,由图片中的文字可以看出Redis项目不正式支持Windows. 但是,Microsoft开放 ...

  3. pycharm下打开、执行并调试scrapy爬虫程序

    首先得有一个Scrapy项目,我在Desktop上新建一个Scrapy的项目叫test,在Desktop目录打开命令行,键入命令:scrapy startproject test1  目录结构如下: ...

  4. [转载]Python使用@property装饰器--getter和setter方法变成属性

    原贴:为什么Python不需要getter和setter getter 和 setter在java中被广泛使用.一个好的java编程准则为:将所有属性设置为私有的,同时为属性写getter和sette ...

  5. Boost.PropertyTree读取ini文件(Linux环境)

    昨天因为需要读取配置文件略略伤神.网上很多例子但是我用都会报错,很多人把Boost.PropertyTree的函数写很麻烦的包所以报错我也不知道什么问题,所以今天整理下. 头上附上官网链接:Boost ...

  6. weblogic修改安装路径教程

    我们有一个安装好的weblogic,我们想再装一个weblogic或者想把weblogic装到别的目录去,最直接的做法是从头装一个. 但是从头装一个是比较费时费力的,尤其是打补丁环节和创domain环 ...

  7. maven plugins

    <build> <finalName>lessons</finalName> <plugins> <plugin> <groupId& ...

  8. jedata日期控件的开始结束日期设置

    <span class="wstxt">开始日期:</span><input type="text" class="wo ...

  9. C#调用接口返回json数据中含有双引号 或其他非法字符的解决办法

    这几天,调用别人接口返回json数据含有特殊符号(双引号),当转换成json对象总是报错, json字符格式如下 { "BOXINFO":[ { ", "ITE ...

  10. POJ 2456 Agressive cows(二分)

    POJ 2456 Agressive cows 农夫 John 建造了一座很长的畜栏,它包括N (2≤N≤100,000)个隔间,这 些小隔间的位置为x0,...,xN-1 (0≤xi≤1,000,0 ...