web前端 - 类🥱

161 阅读3分钟

前言

原因:为了实现继承的方式不显得冗长和混乱,es6引入了class关键字。
原理:原型和构造函数的概念。

定义方式

  1. 🥱类声明式:
 class Person {}
  1. 🥱类表达式:
 Person = class {}

数据类型

typeof Person //function

与函数的区别

  1. 🥱类受块作用域的限制,函数受函数作用域
  2. 🥱类没有声明提升

🥱类的构造函数: new对象时候,执行的步骤。

(1) 在内存中创建一个新对象。

(2) 这个新对象内部的[[Prototype]]指针被赋值为构造函数的 prototype 属性。

(3) 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)。

(4) 执行构造函数内部的代码(给新对象添加属性)。

(5) 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。

实例成员 与原型

每个实例都对应一个唯一的成员对象,这意味着所有成员都不会在原型上共享。

class Person {
    constructor(){ 
        // 添加到 this 的所有内容都会存在于不同的实例上
        this.name = new String('ll')
    }
    //添加到🥱的原型上
   locate(){}
}
const p1 = new Person();     
const p2 = new Person();
console.log(p1.name === p2.name) //false
//调用🥱类方法
p1.locate() 
p2.locate()

static 关键字

class Person {
    static title = 'static title'
    constructor(){
      this.title = 'constructor title'
    }
    //定义在🥱类本身上
    static sayname(){
     console.log(this.title)
    }
    //定义在原型上
    sayname(){
     console.log(this.title)
    }
}
//调用方式
Person.sayname() // static title
new Person().sayname() // constructor title

继承
class Person1 extends Person{}
Person1.sayname() // static title

Person1.title = 'Person title'
Person1.sayname() // Person title

私有属性

class Person{
  //签名加一个 #
  #title = 'this is 私有 title'
  sayTitle(){
      console.log(this.#title)
  }
}
const p = new Person()
p.sayTitle() // this is 私有 title
console.log(p.#title) //报错

迭代器

class Person {
  constructor() {
    this.nicknames = ['Jack', 'Jake', 'J-Dog'];
  }
  // 若不写这个,则返回constructor里面的属性,和类本身非static的属性
  [Symbol.iterator]() {
    return this.nicknames.entries();
  }
}
let p = new Person();
for (let [idx, nickname] of p) {
    console.log(nickname);
}
// Jack
// Jake
// J-Dog

super

1. 只能在派生类里使用
class Person {
    static sayName(){
        console.log('Person static sayName')
    }
    sayName(){
      console.log('Person new sayName')
    }
} 

class Person1 extends Person{
    // 在🥱类构造函数里使用
    constructor(name){
      super(name)//只能这样使用, 并且才能使用this,否则会报错
      this.name = name
    }
    //在静态方法里使用 
    static sayName(){
      super.sayName()
    }
    //实例方法使用
    sayName(){
       super.sayName()
    }
}
Person1.sayName() // Person static sayName
const p = new Person1()
p.sayName() // Person new sayName

!!!! 
1. 不能console.log(super)
2. 在constructor super()执行之后,才能使用this
3. 只能super.[方法],super.[属性]为undefined
4. 只能在派生类使用

TS 中的类🥱

公共(public),私有(private)与受保护(protected)的修饰符
这三个修饰符只能在ts文件里使用,默认的为public
class Person{
  // 不能被继承,只能在Person里使用,不能被实例化
  private name1 = 'private name' 
  // 可被继承,不能被实例化
  protected name2 = 'protected name'
  
  sayName1(){
    console.log(this.name1) //private name
  }
  
  sayName2(){
    console.log(this.name2) //protected name
  }
}

class Person1 extends Person {
  sayName1(){
    console.log(this.name1) // error 报错 Property 'name1' is private and only accessible within class 'Person'.
  }
  sayName2(){
      console.log(this.name2)//protected name
  }
}

const p = new Person1()
p.name1 //error

图片.png

Readonly

只能读取 不能设置

class Person{
  readonly name = 'aaa'
  constructor(){
    this.name = 'll' //error
  }
}

抽象类 abstract

抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。

abstract class Person{
  abstract sayName():viod;//必须在派生类实现
}