初识Class
传统的写法
function Point(x, y) {
this.x = x
this.y = y
}
Point.prototype.toString = () => {
return `( ${this.x}, ${this.y} )`
}
ES6为了更接近面向对象的编程方式,提供了Class的概念
class Point {
constructor (x, y) {
this.x = x
this.y = y
}
toString {
return `( ${this.x}, ${this.y} )`
}
}
上面定义了一个‘类’,一个构造方法constructor,this是实例对象,一个toString方法(注意没有function这个保留字)
class类中的方法(除constructor之外)其实都定义在类的prototype属性上
// 比如toString(),相当于
Point.prototype = {
toString(){}
}
// 所以类的新方法可以这样添加进去
Object.assign(Point.prototype, {
toString(){},
toValue(){}
})
Point.prototype.constructor === Point // true
构造方法和实例对象
通过new命令生成对象实例时都默认自动调用constructor
方法,一个类必须有constructor
方法,没有显式定义的话,一个空的con
方法会被默认添加
constructor () {}
该方法默认返回实例对象(就是this),但是可以指定返回另一个对象
class Foo {
constructor {
return Object.create(null)
}
}
new Foo() instanceof Foo // false
实例对象的创建同之前一样
class Point {
// 这里为了缩小工作量,没有全部书写
constructor () {}
tostring () {}
}
let point = new Point(2, 3)
point.toString() // (2, 3)
point.hasOwnProperty('x') // true,因为该实例属性显式的定义在this上
point.hasOwnProperty('toString') // false,因为方法都是定义在原型上的
point.prototype.hasOwnProperty('toString') // true
point._proto_ === Point.prototype // true
ES6的Class只是ES5的构造函数的一层包装,所以继承了函数的许多属性,包括name属性
class Point {}
Point.name // 'Point'
class不存在变量提升
new Foo() // ReferenceError
class Foo {}
// let Foo = class {}
// class Bar extends Foo {}
// 因为class没有提升,所以上面代码不会报错
class的继承
class childPoint extends Point {
constructor(x, y, color) {
super(x, y)
this.color = color
}
toString() {
return this.color + '' + super.toString() // 等于Parent.toString()
}
}
子类必须在constructor方法中调用super方法,否则新建实例会出错。另外只有调用super之后,才可以使用this关键字
class Point{}
class childPoint extends Point{
constructor (x, y, color) {
this.color = color // ReferenceError
super(x, y)
this.color = color // 正确
}
}
let cp = new childPoint() // ReferenceError
子类的_proto_属性
class B extends A {
}
B._prototype_ === A // true
B.prptotype._proto_ === A.prototype // true
Object.getPrototypeof(B) === A // true
getter和setter
class MyClass {
get prop() {
return 'getter'
}
set prop(value) {
console.log('setter:' + value )
}
}
let inst = new MyClass()
inst.prop = 123 // setter: 123
inst.prop // 'getter'
Class的静态方法,在一个方法前面,加上static关键字,就表示该方法不会被实例继承,但是可以被子类继承
class Foo {
static classMethod () {
return 'hello'
}
}
Foo.classMethod() // hello
let foo = new Foo()
foo.classMethod() // TypeError: undefined is not a function
// 但是可以被子类继承,也可从super上调用
class Bar extends Foo {
// static classMethod() {
// return super.classMethod() + ', too'
// }
}
Bar.classMethod() // hello