重学ES6(十)Class

209 阅读2分钟

基础知识

JavaScript 中,生成实例对象的传统方法式通过构造函数

function Point (x, y) {
	this.x = x
    this.y = y
}

Point.prototype.toString = function() {
	return '(' + this.x + ',' + this.y + ')'
}

var p = new Point(1, 2)

使用 ES6 的 class 改造

class Point {
	constructor (x, y) {
    	this.x = x
        this.y = y
    }
    
    toString () {
    	return '(' + this.x + ',' + this.y + ')'
    }
}

所以 ES6 中的类,完全可以看作构造函数的另一种写法

class Point {
  // ...
}
typeof Point // "function"
Point === Point.prototype.constructor // true

上面代码就可以看出来,类的数据类型就是函数,类本身也就指向了构造函数。

使用的时候,也是直接对类使用 new 命令,跟构造函数的用法完全一致。

class Bar {
	test() {
    	console.log('test')
    }
}

var b = new Bar()
b.test()		// 'test'

构造函数的 prototype 属性,在 ES6 的类上继续存在的。类的所有所发都式定在函数的 prototype 属性上面的。

class Point {
	constructor () {
    
    }
    toString () {
    
    }
    toValue () {
    
    }
}
// 等同于
Point.prototype = {
	constructor() {},
    toString() {},
    toValue() {}
}

在类的实例上面调用方法,其实就是调用原型上的方法

class B {}
let b = new B()
b.constructor === B.prototype.constructor

constructor 方法 constructor 方法式类的默认方法,通过 new 命令生成对象实例时,自动调用该方法。一个类必须有 constructor 方法,如果没有显式定义,一个空的 construct 方法会被默认添加。

class Point {}

// 等同于
class Point {
	constructor() {}
}

取值函数 getter 和 存值函数 setter

class Myclass {
    constructor() {

    }

    get prop() {
        return 'getter'
    }
    set prop(value) {
        console.log('setter' + value)
    }
}

let inst = new Myclass()

inst.prop = 123
// setter 123

inst.prop
// getter

静态方法

类相当于实例的原型,所有类中定义的方法,都会被实例继承。如果一个方法前,加static关键字,就表示该方法不会被实例继承,而是直接通过类来调用。

class Foo {
	static method() {
    	return 'hello world'
    }
}

Foo.method()	// 'hello world'

var foo = new Foo()
foo.method		// TypeError

父类的静态方法可以被子类继承

class Foo {
	static method() {
    	return 'hello world'
    }
}

class Bar extends Foo {}

Bar.method()		// 'hello world'

静态方法也是可以从 super 对象上调用的

class Foo {
	static method() {
    	return 'hello world'
    }
}

class Bar extends Foo {
	static method() {
    	return super.method() + ',too'
    }
}

Bar.method()	//	'hello world,too'

class的继承

class 可以通过 extends 关键字实现继承,这比ES5通过原型链实现继承,要方便很多。

class Point {}

class ColorPoint extends Point {
	constructor (x, y, color) {
    	super(x, y)		//	调用父类的 constructor(x, y)
        this.color = color
    }
    toString() {
    	return this.color + ' ' + super.toString()
        // 调用父类的 toString()
    }
}

Object.getPrototypeOf() Object.getPrototypeOf 方法可以用来从子类上获取父类

Object.getPrototypeOf(ColorPoint) === Point

可以使用这个方法判断 一个类是否继承了另一个类

类的 prototype 和 [[prto]]

class A {}

class B extends A {}

B.__proto__ === A		// true
B.prototype.__proto__ === A.prototype	// true

产生上面代码的结果是因为,类的继承是按照下面方式实现的

class A {}

class B {}

// B 的实例继承 A 的实例
Object.setPrototypeOf(B.prototype, A.prototype)

// B 继承 A 的静态属性
Object.setPrototypeOf(B, A)

// 对于 Object.setPrototypeOf 具体实现
Object.setPrototypeOf = function (obj, proto) {
	obj.__proto__ = proto
    return obj
}