ES5是没有类这个东西,虽然可以写出看起来像类的代码
js
function Cat (name, color) {
let ret = Object.create(Cat.prototype)
ret.name = name
ret.color = color
return ret
}
Cat.prototype = {
say: function() {
console.log('say', this.name)
},
eat: function() {
console.log('eat')
}
}
// 使用
let BlackCat = Cat('Lily', 1)
BlackCat.say()
// => say lily
到了ES6,有了比较正经的写法
js
class Cat {
constructor(name, color) {
this.name = name
this.color = color
}
say() {
console.log('say', this.name)
}
eat() {
console.log('eat')
}
}
// 使用
let BlackCat = new Cat('Lily','black')
BlackCat.say()
// => say lily
因为有了构造函数 constructor
看起来就比较像传统类
类里的所有方法,包括构造函数,都是定义在原型链 prototype
上
类里定义的方法,用 Object.keys(Cat)
是无法枚举的,直接返回空数组,这点有区别于 Cat.prototype.say
而且无法使用 hasOwnProperty()
来判断实例有没某个方法
js
BlackCat.hasOwnProperty('say')
// => false
BlackCat.__proto__.hasOwnProperty('say')
// => true
虽然可以从原型链判断方法,但是依旧并无法枚举原型链上的方法
js
Object.keys(BlackCat)
// -> ["name", "color"]
Object.keys(BlackCat.__proto__)
// -> []
同个类的实例化对象,共享同个原型对象
js
let BlackCat = new Cat('Lily','black')
let GreyCat = new Cat('Nana','grey')
BlackCat.prototype === GreyCat.prototype
// => true
类的方法名支持表达式,比如
js
const funName = 'jump'
class Cat {
[funName]() {
console.log(funName)
}
}
此外也支持Generator方法
js
class Cat {
* sleep() {
console.log('sleep')
}
}
(Generator使用见这篇 {% post_link 'Web/异步回调之generator(1)入门篇' '异步回调之generator(1)入门篇' %})
js
class Cat {
constructor(nane, color) {
this.name = name
this.color = color
}
say() {
console.log('say')
}
static sleep() {
console.log('sleep')
this.say() // <- 这里会报错,因为this指向undefined
}
}
Cat.sleep()