Skip to content

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()

上次更新于: