2015年,ECMAScript 6(ES6)标准引入了类。
JavaScript有一种相当不常见的方式来实现继承:原型继承。原型继承,虽然在我看来很好,但与其他大多数流行的编程语言对继承的实现不同,它是基于类的。
来自Java、Python或其他语言的人很难理解原型继承的复杂性,所以ECMAScript委员会决定在原型继承的基础上撒上语法糖,使其类似于其他流行实现中基于类的继承的工作方式。
这一点很重要。在引擎盖下的JavaScript仍然是一样的,你可以用通常的方式访问一个对象的原型。
一个类的定义
这就是一个类的样子。
class Person {
constructor(name) {
this.name = name
}
hello() {
return 'Hello, I am ' + this.name + '.'
}
}
一个类有一个标识符,我们可以用它来创建新的对象,new ClassIdentifier() 。
当对象被初始化时,constructor 方法被调用,并传递任何参数。
一个类也有它所需要的许多方法。在这种情况下,hello 是一个方法,可以在所有从这个类派生的对象上调用。
const flavio = new Person('Flavio')
flavio.hello()
类的继承
一个类可以扩展另一个类,使用该类初始化的对象会继承两个类的所有方法。
如果被继承的类有一个与层次结构中较高的一个类同名的方法,则最接近的方法优先使用。
class Programmer extends Person {
hello() {
return super.hello() + ' I am a programmer.'
}
}
const flavio = new Programmer('Flavio')
flavio.hello()
(上面的程序打印出 "你好,我是Flavio,我是一个程序员。")
类没有明确的类变量声明,但你必须在构造函数中初始化任何变量。
在一个类中,你可以引用父类,调用super() 。
静态方法
通常,方法是在实例上定义的,而不是在类上。
静态方法是在类上执行的。
class Person {
static genericHello() {
return 'Hello'
}
}
Person.genericHello() //Hello
私有方法
JavaScript没有一个内置的方法来定义私有或受保护的方法。
有一些变通方法,但我不会在这里描述它们。
获取器和设置器
你可以添加以get 或set 为前缀的方法来创建一个getter和setter,这是两段不同的代码,根据你要做的事情来执行:访问变量,或修改其值。
class Person {
constructor(name) {
this._name = name
}
set name(value) {
this._name = value
}
get name() {
return this._name
}
}
如果你只有一个getter,这个属性就不能被设置,任何这样做的尝试(在构造函数之外,当你用这个类初始化一个新对象时,构造函数会设置这个值)都会被忽略。
class Person {
constructor(name) {
this._name = name
}
get name() {
return this._name
}
}
如果你只有一个设置器,你可以改变值,但不能从外部访问它。
class Person {
constructor(name) {
this._name = name
}
set name(value) {
this._name = value
}
}
当你想在改变属性值时执行一些代码,或者你想创建一个 "计算 "属性时,Getters和setter非常有用。你可以通过使用一个getter来改变你返回的值。
你也可以运行一些代码,比如当一个值被改变时,记录到控制台或一个文件中。