ECMAScript6新引入了class关键字具有正式定义类的能力,类(class)是ECMAScript中新的基础性语法糖结构,类的语法可以非常方便的定义应该存在于实例上的成员,应该存在于原型上的成员,以及应该存在于类本身的成员。
1. 类定义
与函数相似,定义类也有两种主要方式:类声明和类表达式。这两种方式都使用class关键字加大括号
class Person {} // 类声明
console.log(Person) // class Person {}
console.log(typeof Person) // function
const Animal = class {} // 类表达式
注意:
类表达式与函数表达式形似,在被求值前也不能引用;
类声明式与函数声明式不同,函数表达式可以提升,但类不能;
函数受函数作用域限制,而类受块作用域限制;
console.log(FunPerson) // FunPerson () {}
function FunPerson () {}
console.log(FunPerson ) // FunPerson () {}
console.log(ClassPerson) // ReferenceReeor: ClassPerson is not defined
class ClassPerson {}
console.log(ClassPerson ) // ClassPerson {}
{
function FunPerson () {}
class ClassPerson {}
}
console.log(FunPerson) // FunPerson () {}
console.log(ClassPerson) // ReferenceReeor: ClassPerson is not defined
2. 类的构成
类可以包含构造函数方法、实例方法、获取函数、设置函数、静态类方法,但这些都不是必须的,空的类定义照样有效
class Person {
constructor(name) { this.name = name} // 构造函数方法
get myName() {} // 获取函数
static myAge() {} // 静态方法
getName() { return this.name } // 实例方法
}
let p = new Person('tom')
console.log(p.getName() ) // tom
3. 类构造函数
类的内部工作机制就是原型操作,constructor关键字用于在类定义块内部创建类的构造函数,在使用new操作符创建类的实例时,会调用constructor函数
class Person {
constructor(name) {
this.name = name // 类把属性写在constructor类构造函数里
}
show() {} // 类把公共方法写这里
}
console.dir(Person) // 与构造函数的结构类似
console.log(Person === Person.prototype.constructor) // true
function Animal(name) {
this.name = name // 构造函数把属性写这里
}
Animal.prototype.show = function() {} // 构造函数把公共方法写在原型上
console.dir(Animal)
console.log(Animal=== Animal.prototype.constructor) // true
使用类new调用类的构造函数会执行以下操作:
- 在内存中创建一个新对象;
- 这个新对象内部的[[prototype]] 指针被赋值为构造函数的prototype属性;
- 构造函数内部的this被赋值为这个新对象,即this指向新对象;
- 执行构造函数内部的代码,给新对象添加属性;
- 如果构造函数返回非空对象,则返回该对象,否则,返回刚创建的新对象
4. 实例、原型和类成员
4.1 实例成员:
每次通过new调用类标识符时,都会执行类构造函数,在这个函数内部,可以为新创建的实例添加“自有”属性,在构造函数执行完毕后。仍然可以给实例继续添加新成员,每个实例都对应一个唯一的成员对象,这意味着所有成员都不会在原型上共享。
class Person {
constructor() {
this.name = new String('jake') // 添加到this的所有内容都会存在于不同的实例上
}
show() {}
}
let p1 = new Person(),
p2 = new Person()
console.log(p1.name === p2.name ) // false
4.2 原型方法
为了在实例间共享方法,类定义语法把在类块中定义的方法作为原型方法。
类定义也支持获取和设置访问器,与普通函数一样
class Person {
constructor() {
this.name = new String('jake')
}
show() {} // 在类块中定义的所有内容都会定义到类的原型上
set age(newval) { this.age = newval}
get age() { return this.age}
}
let p1 = new Person()
console.log(p1) // {name: 'jake', __proto__: {constructor: class Person }, show: f show(), __proto__: Object}
p1.age = 18
console.log(p1.age) // 18
4.3 静态类方法
与原型成员相似,静态成员每个类上只能有一个,使用static关键字作为前缀,常用于执行不特定于实例的而操作,不要求存在类的实例
class Person {
constructor() {
this.name = new String('jake')
}
static show() { console.log(this) } // 定义在类本身上
}
let p1 = new Person()
Person.show() // class Person {}