ES6的class出来后,我们再也看不到那烦人的prototype了,因为我之前用的是java语言开发,看到这个class就非常熟悉,现在赶紧来学习一下它的语法,然后总结一波
1.定义类
class Point {
// new Point()的时候会自动执行构造方法,返回一个新的对象,this绑定到该对象
constructor(x, y) {
this.x = x;
this.y = y;
}
// 类中定义的方法默认定义在原型对象上,且是不可枚举的
toStr() {
console.log(`${this.x}, ${this.y}`);
}
}
- 类里面必须有constructor方法,它做了以下几件事(其实和es5一毛一样)
- 创建一个新对象
- this指向这个新对象
- 对象添加属性
- 给这个新对象设置关联对象
- 返回对象
- 验证一波
const p = new Point(666, 888)
console.log(Object.getOwnPropertyNames(p)); // ['x', 'y']
console.log(Object.getPrototypeOf(p) === Point.prototype); // true
- 类中的方法不需要function,这样会报错,用fn(){}这样声明方法,另外类中的方法默认添加到类的prototype属性指向的对象上面,且是不可枚举的
// Object.getOwnPropertyNames获得自身对象的所有属性名字,包括不可枚举的(不含关联对象的)
// Object.keys获得自身对象的所有属性名字,不包括不可枚举的(不含关联对象的)
console.log(Object.getOwnPropertyNames(Point.prototype)); // ['constructor', 'toStr']
console.log(Object.keys(Point.prototype)); // []
// for in 获得整个原型链上面的可以枚举的所有属性名
Point.prototype.a = 1
Point.prototype.test = function (){}
Object.prototype.x = function (){}
for(let k in Point.prototype){
console.log(k); // a test x
}
2.继承
class ColorPoint extends Point {
constructor(x, y, m, n) {
super(x, y);
// 可以通过浅拷贝的方式,再加上解构来赋值
// this.m = m;
// this.n = n;
Object.assign(this, { m, n })
}
toStr2() {
super.toStr();
}
test() {
super.num = 666
}
}
这里有三点需要注意:
【注意点1】 在子类的constructor方法里面,第一行必须是super(),为什么呢?
这边我摘抄了阮一峰老师的解答
super在这里表示父类的构造函数,用来新建一个父类的实例对象
ES6 规定,子类必须在constructor()方法中调用super(),否则就会报错。
这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造后返回
如果不调用super()方法,子类就得不到自己的this对象
为什么子类的构造函数,一定要调用super()?原因就在于 ES6 的继承机制,与 ES5 完全不同。ES5 的继承机制,是先创造一个独立的子类的实例对象,然后再将父类的方法添加到这个对象上面,即“实例在前,继承在后”。ES6 的继承机制,则是先将父类的属性和方法,加到一个空的对象上面,然后再将该对象作为子类的实例,即“继承在前,实例在后”。这就是为什么 ES6 的继承必须先调用super()方法,因为这一步会生成一个继承父类的this对象,没有这一步就无法继承父类。
但我看完更加懵逼了,我觉得讲的不正确,因为继承关系,说到底就是两个对象之间建立关联,具体见我上一篇笔记,下面发表一下我的观点:
相当于Point.prototype.constructor.call(this, x, y)
然后父类构造函数执行刚刚说的5件事,然后我们子类构造函数拿着返回的对象继续加工
class ColorPoint extends Point {
constructor(x, y, m, n) {
super(x, y);
Object.assign(this, { m, n })
}
}
【注意点2】 如何调用父类方法?
使用super.调用父类方法,相当于Point.prototype.toStr.call(this)
toStr2() {
super.toStr();
}
【注意点3】 使用super赋值
赋值操作时,这里不是Point.prototype.num = 666,而是this.num = 666,这里是一个坑,不方便理解,只能死记硬背
test() {
super.num = 666
}
下面验证一波
const color = new ColorPoint(1, 2, 3, 4)
console.log(Object.getOwnPropertyNames(color)); // x y m n
console.log(Object.getOwnPropertyNames(ColorPoint.prototype)); // ['constructor', 'toStr2']
console.log(Object.getPrototypeOf(color) === ColorPoint.prototype); // true
console.log(Object.getPrototypeOf(ColorPoint.prototype) === Point.prototype); // true
color.toStr2() // 1, 2
color.test()
console.log(Object.getOwnPropertyNames(color)); // x y m n num
console.log(color.num); // 666
网友评论