class的继承
- class通过extends实现继承父类所有的属性和方法,用super关键字新建父类的this
|
|
Object.getPrototypeOf() 可以从子类上获取父类
1Object.getPrototypeOf(ColorPoint) === Point //可以用来判断一个类是否继承了另外一个类super关键字
当做函数来使用时,代表父类的构造函数 ,ES6 要求,子类的构造函数必须执行一次
super
函数。1234567class A{}class B extends A{constructor(){super() //super是一个函数}}**这里super()虽然代表了父类A的构造函数,但是返回的是子类B的实例,即super内部的this指的是B,作为对象时,super指向父类的原型对象 。(所以父类实例上的方法或者属性无法取得,只有定义在父类原型对象上的才能取到)
1234567891011class A = {p(){return 2 //constructor 是定义实例上的方法或属性,不在这上面的定义在prototype上}}class B extends A{constructor(){super()console.log(super.p()) //这里super.p()就相当于A.prototype.p()}}123456789101112131415161718192021#ES6 规定,通过super调用父类的方法时,super会绑定子类的this。class A {constructor(){this.x = 1}print(){console.log(this.x)}}class B extends A{constructor(){super() //super内部的this指的是Bthis.x = 2}m(){super.print()}}let b = new B()b.m() //2* super.print()虽然调用的是A.prototype.print(),但是A.prototype.print()会绑定子类B的this,导致输出的是2,而不是1。
class
类的所有方法都定义在prototype对象上
123class A{}let a = new A()a.constructor === A.prototype.constructor可以用Object.assign()方法来向类添加方法(在类的原型上,即原型.prototype)
1234567891011class A{constructor(){sayHi(){}sayGoodBye(){} //类中不需要添加逗号}}Object.assign(A.prototype,{ //里面是大括号括起来的对象toString(){},toValue(){}})定义在类内部的方法,是不可枚举的;但是es5的老写法,是可以枚举的
12345678910111213141516class Point {constructor(){}sayHi(){}}var a = new Point()--------Object.keys(Point.prototype) //[]Object.getOwnPropertyNames(Point.prototype) ["constructor","sayHi"]------Object.getPrototypeOf(a) //a的原型原型.prototype.isPropertyOf(实例)实例 instanceof 原型--------a.__proto__.hasOwnProperty("sayHi") //true,拥有自己的属性Object.defineProperty()Object.getOwnPropertyDescriptor()类的属性名可以采用表达式,用[]括起来
123456789let kk = 'toString'class A{constructor{//....}[kk](){//....}}constructor方法是默认方法,当new的时候,自动调用该方法。该方法默认返回实例对象(即this)
实例的属性除非显式定义在其本身(即定义在
this
对象上),否则都是定义在原型上(即定义在class
上)123456789101112131415class Point {constructor(x, y) {this.x = x;this.y = y;}toString() {return '(' + this.x + ', ' + this.y + ')';}}var point = new Point(2, 3);point.toString() // (2, 3)point.hasOwnProperty('x') // truepoint.hasOwnProperty('y') // truepoint.hasOwnProperty('toString') // falsepoint.__proto__.hasOwnProperty('toString') // true表达式
123456789101112131415161718const MyClass = class Me{ //这里类的名字是MyClass而不是Me,可以const MyClass = class{}constructor(){//...}}--------------立即执行的classlet person = new class{constructor(name){this.name = name}sayName(){console.log(this.name)}}('tom')person.sayName()-------------name属性,总是返回紧跟在class后面的类名this指向
123456789101112131415161718192021222324252627282930class Logger{print(text){console.log(text)}printName(name = 'there'){this.print(`name:${name}`)}}const logger = new Logger();const { printName } = logger;printName(); // TypeError: Cannot read property 'print' of undefined//this 指向调用时的坏境,此时找不到print方法--------------绑定this只能在constructor中绑定,用bind方法或者箭头函数class Logger{constructor(){this.printName = this.printName.bind(this)}//...}------class Logger{constructor(){this.printName = (name = 'there')=>{this.print(`name:${name}`)}}print(text){console.log(text)}}静态方法,静态方法里面的this直的是这个类,而不是实例
123456789101112class Foo {static bar () {this.baz(); //静态方法里面的this调用的是 静态方法baz}static baz () {console.log('hello');}baz () {console.log('world');}}Foo.bar() // hello静态方法的继承
1234567891011121314class Foo {static classMethod() {return 'hello';}a(){console.log(1)}}class Bar extends Foo {}Bar.classMethod() // 'hello'let a = new Bar() //这里实例化后再调用类的方法a.a() //1123456789101112可以通过super.xxx来调用class Foo {static classMethod() {return 'hello';}}class Bar extends Foo {static classMethod() {return super.classMethod() + ', too';}}Bar.classMethod() // "hello, too"静态属性:静态属性指的是 Class 本身的属性,即Class.propName,而不是定义在实例对象(this)上的属性。
123class Foo {static a=1}继承时,super就是指被继承的构造函数
123456789class ColorPoint extends Point {constructor(color) { //这里的constructor里面传的参数是ColorPoint实例的super(x, y); // 调用父类的constructor(x, y),必须调用super之后才会有thisthis.color = color; //super是可以直接在里面传对应的父类参数}toString() {return this.color + ' ' + super.toString(); // 调用父类的toString()}}Object.getPrototypeOf() 用来判断一个类是否继承了另外一个类
1Object.getPrototypeOf(ColorPoint) === Point //true