ES6 中class的继承用法详解(2)

class Father { constructor () { this.x =1;//这个this指向的是Father对象的实例 } print () { console.log(this.x); } } class Son extends Father { constructor () { super(); this.x = 2;//这个this指向的是Son对象的实例 } m() { super.print(); } } let s = new Son(); s.m(); //2

super.print()虽然调用的是Father.prototype.print(),但是Father.prototype.print()会绑定子类Son的this,导致输出的是2,而不是1,也就是说,实际上执行的是 super.print.call(this)。

如果super作为对象,用在静态方法中,这时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(1); //static 1 var child = new Child(); child.myMethod(2); //instance 2

super在静态方法之中指向父类,在普通方法之中指向父类的原型对象。
注意,使用super的时候,必须显式指定是作为函数、还是作为对象使用,否则会报错。
类的prototype属性和proto属性
大多数浏览器的ES5实现之中,每一个对象都有proto属性,指向对应的构造函数的prototype属性,class作为构造函数的语法糖,同时有prototype属性和proto属性,因此同时存在两条继承链;
(1)子类的proto属性,表示构造函数的继承,总是指向父类;
(2)子类prototype属性的proto属性,表示方法的继承,总是指向父类的prototype属性;

class A{ } class B{ } //B的实例继承A的实例 Object.setPrototypeOf(B.prototype, A.prototype); //B 的实例继承A的静态属性 Object.setPrototypeOf(B,A); const b = new B();

《对象的扩展》一章中Object.setPrototypeOf()方法的实现:

Object.setPrototypeOf = function (obj, proto) { obj.__proto__ = proto; return obj ; }

因此

Object.setPrototypeOf( B.prototype , A.prototype ); //等同于 B.prototype.__proto__ = A.prototype ; Object.setPrototypeOf(B, A); //等同于 B.__proto__ = A;

这两条继承链,可以理解为:作为一个对象,子类B的原型(proto属性)是父类(A);作为一个构造函数,子类B的原型对象(prototype属性)是父类的原型对象(prototype)的实例;

extends的继承目标
extends关键字后面可以跟很多类型的值;

class B extends A{ }

只要A有一个prototype属性的函数,就能被B继承,由于函数都有prototype属性(除了Function.prototype函数),因此A可以使任意函数,下面三种情况:
(1)子类继承Object类

class A extends Object { } A.__proto__ === Object //true; A.prototype.__proto__ === Object.prototype //true

这种情况就是 : A就是构造函数Object的复制,A的实例就是Object的实例
(2)不存在任何继承

class A { } A.__proto__ === Function.prototype //true A.prototype.__proto__ = Object.prototype //true

这种情况是:A作为一个基类(不存在任何继承),就是一个普通的函数,所以直接继承Function.prototype。但是A调用后返回一个空对象(即Object实例),所以A.prototype.proto指向构造函数(Object)的prototype属性;
实例的proto属性
子类实例的proto属性的proto属性,指向父类实例的proto属性。也就是说,子类的原型的原型,是父类的原型。

原生构造函数的继承
原生构造函数是指语言内置的构造函数,通常用来生成数据结构。

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

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

vue使用

testClass.js

//定义类 class Person{ // 构造 constructor(x,y){ this.x = x; this.y = y; } //定义在类中的方法不需要添加function toString(){ return (this.x + "的年龄是" +this.y+"岁"); } } export { Person };

test.vue

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/1714d47490dc0a4afc6dab576b880f2d.html