前言BB
ECMAScript 2015 中引入的类(Class)实际上是基于原型的继承的语法糖。不是新的面向对象的继承模型。
其实我用的并不多,写写小活动啥的也用不上。
之前用来写了个小后台,ThinkJS 内部就使用的 Class 的形式。
体验了一下,然后因为写起来不太爽放弃了,vue + TypeScript。
也是体验了一下,Angular 。
Class
可以理解为特殊的函数(必须 New。声明提升,死区。执行在严格模式)
声明
class Point { constructor(x, y) { this.x = x; this.y = y; } } class Circle { constructor(point, r) { this.point = point; this.r = r; } } 等价于 function Circle(point, r){ this.point = point; this.r = r; } new Circle([50, 50], 10)
构造函数 Constructor
当 New
一个对象的时候,做了几件事?
- 初始化一个空对象
- 绑定 this
- 执行构造函数
- 返回这个对象(不需要
return
来返回)
因为类是可以继承的,所以可以使用 super
关键字来调用父类的构造函数。
class Circle { constructor(point, r) { // super() //这样来调用父类的构造函数 this.point = point; this.r = r; } }
原型链方法
class Circle { constructor(point, r) { this.point = point; this.r = r; } // 原型链方法,实例化之后可以计算面积 get area() { console.log('get area') return this.calcArea() } // 原型链方法,实例化之后可以计算面积 calcArea() { return Math.PI * Math.pow(this.r, 2) } } //new Circle([50, 50], 20)
原型方法、静态方法、静态字段
class Point { static staticField = 'static field'; constructor(x, y) { this.x = x; this.y = y; } static distance(a, b) { const dx = a.x - b.x; const dy = a.y - b.y; return Math.hypot(dx, dy); } } const p1 = new Point(5, 5); const p2 = new Point(10, 10); console.log(Point.distance(p1, p2));
属性声明
class Point { x=0 y=0 constructor(x, y) { if(x)this.x = x; if(y)this.y = y; } } new Point()
内部属性声明
类似于之前的闭包内的变量
class Rectangle { #height = 0; #width; constructor(height, width) { this.#height = height; this.#width = width; console.log(this.#height) } } rect = new Rectangle(1,2) // rect.#height
继承
如果子类中存在构造函数,则需要在使用 this
之前首先调用 super()
。
class Animal { name='Breaux'; constructor(name) { this.name = name; } speak() { console.log(this.name + ' makes a noise.'); } } class Dog extends Animal { age = 0; constructor(age) { super('Mitzie') this.age = age; } speak() { console.log(this.name + ' barks.'+`age: `+this.age); } } var d = new Dog(10); d.speak();// 'Mitzie barks.age: 10'
验证
New
提升&死区
严格模式