1.Class简介
class Person{
constructor(name, id){
this.name = name
this.id = id
}
toString(){
return `${name}: ${id}`
}
}
1.1 class特性
- 本质上是一个
函数
- 默认严格模式
- 不存在提升行为
name
属性是class关键字后面的类名- 内部
[Symbol.iterator]
表示Generator函数
在类中的方法都会定义在prototype
上面
class Person{
constructor(name, id){
this.name = name;
this.id = id;
}
toString(){
return `${this.name}: ${this.id}`
}
toValue(){
return this.id
}
}
Object.getOwnPropertyNames(Person.prototype) // ['constructor','toString','toValue']
// 等同于
Person.prototype = {
constructor() {},
toString() {},
toValue() {},
}
Object.defineProperty(Person.prototype,'constructor',{
value: Person,
writable:false,
enumerable: false, // 不可枚举喔~
configurable: false
})
类的getter/setter
class Person {
constructor(name, id) {
this.name = name
this.id = id
}
get _id() {
return this.id + 1
}
set _id(value){
this.id = value
}
}
const p = new Person('jack', 107)
console.log(p._id) // 108
console.log(p.id) // 107
p._id = 100
console.log(p.id) // 100
this默认指向类实例,但是单独抽离出来会出现错误
class Person {
constructor(name){
this.name = name
}
sayName(){
this.print(this.name)
}
print(text){
console.log(text);
}
}
const p = new Person('jack')
p.sayName() // jack
// 抽离出来
const{sayName} = p
sayName() // print is not defined
改进
constructor(name){
this.name = name
this.sayName = this.sayName.bind(this)
}
2.Class静态方法
在一个方法前加上static
关键字时,会定义方法在类上而非原型上,称为静态方法
,即静态方法是供类调用的,非静态方法是供实例调用的
class Foo {
static classMethod() {
return 'hello'
}
}
Foo.classMethod() // 'hello'
var foo = new Foo()
foo.classMethod() // TypeError: foo.classMethod is not a function
在static静态方法中,this指向的是类,而非实例
,同时静态方法名可以与非静态方法名重名
class Foo {
static bar() {
this.baz()
}
static baz() {
console.log('class')
}
baz() {
console.log('instance.prototype')
}
}
Foo.bar() // class
可以通过super
关键字访问父类,以访问到父类中的静态方法
class Foo {
static fn() {
return 'hello'
}
}
class Bar extends Foo {
static fn() {
return super.fn() + ', too'
}
}
Bar.fn() // "hello, too"
3.Class实例、原型、静态属性方法定义
不多bb了,直接上代码
class Person{
constructor(name){
this.name = name // instance.name
}
id=1008 // instance.id
sayId = function(){ return this.id}// instance.sayId
sayName(){ return this.name} // prototype.sayName
get name(){ return 'jack' } // prototype.name (getter/settter)
set name(newVal,oldVal){
this.name = newVal
console.log(`new:${newVal},old:${oldVal}`)
}
static cId = 1007 // constructor.cId
static sayHello(){ return 'hello' } // constructor.sayHello
}
4.静态块
ES2022引入了静态块
,允许在类的内部设置一个代码块,在类生产时运行一次,主要用于对静态属性的初始化
class C {
static x = ...;
static y;
static z;
static {
let obj = doSomethingWith(this.x)
this.y = obj.y
this.z = obj.z
}
}
5.Class继承
5.1 extends关键字
在定义子类时,使用extends
关键字指定其父类,在子类内部通过super
指向父类,super()
方法调用父类的constructor
class Father {
constructor(name, id) {
this.name = name
this.id = id
}
fn1() { ... }
static fn2(){ ... }
}
class Son extends Father {
constructor(name, id, age) {
super(name, id) // 调用父类的constructor
this.age = age
}
fn1() {
return super.fn1() + this.age // 调用父类的fn1()
}
}
注意: 子类必须在constructor()
构造方法中调用super()
方法来完成构造,从而获得与父类同样的实例属性和方法,再对其进行扩展
若子类没有定义constructor方法会默认添加
class Son extends Father{}
//等同于
class Son extends Father{
constructor(...args){
super(...args)
}
}
由于调用super方法,才能通过父类的构造函数创建子类实例,故this
(指向子类实例)要在super后才有定义
class Point {
constructor(name, id) {
this.name = name
this.id = id
}
}
class ColorPoint extends Point {
constructor(name, id, color) {
this.color = color // ReferenceError
super(name, id) // 通过父类构造函数创建子类实例
this.color = color // 正确
}
}
5.2 super关键字
在子类构造函数中必须要先调用super()
,这时候会执行父类构造函数,并将this执行创建的子类实例
class A {
constructor() {
console.log(new.target.name)
}
}
class B extends A {
constructor() {
super()
}
}
new A() // A
new B() // B