JS面向对象class

108 阅读4分钟

Class 简介

  1. Javcscript语言中, 生成实例对象的传统方法是通过构造函数
  2. ES6提供了接近其他传统语言的写法, 引入了Class类的概念, 可以作为对象的模板
  3. 可以用instanceof来检查是对象是否由某个类创建, 如果是, 该对象是这个类的实例

语法

一. 声明

  • class 类名 = {} // 类名要使用大驼峰命名
  • const 类名 = class {}

二. 创建实例

  • new 类()
// const Person = class {}

// Person类专门用来创建人的对象
class Person {}
const p1 = new Person() // 使用构造函数创建对象
const d1 = new Dog()
console.log(p1 instanceof Person) // true //  检查p1是否是由Person创建的

属性

  • class的代码块默认为严格模式. 属性分为实例属性静态属性, 静态属性的声明需要使用static关键字, 实例属性通过实例去访问, 静态属性通过类访问
class Person {
     name = '孙悟空' // Person的实例属性 name
     age = 18 // 实例属性只能通过实例访问
     static test = 'test静态属性' // 使用static声明的属性, 是静态属性(类属性)
     static hh = 123 
 }

const p1 = new Person()
console.log(Person.hh) // 123
console.log(Person.age)  // undefined
console.log(p1) // Person

方法

  • class的方法和属性一致, 分为实例方法静态方法, 调用方式和属性一致
class Person {
   name = '张三'
   sayHello = function () {} // 添加方法的一种方式
   sayhello() {
      console.log('哈哈哈' + this.name)
   } // 实例方法, 方法中this就是当前实例
   static test() {
      console.log('我是静态方法')
   } // 静态方法(类方法) 通过类来调用
}
const p1 = new Person()
Person.test() // 我是静态方法
p1.sayHello() // 哈哈哈 我是张三

构造函数

  1. 为了解决同一类创建的实例的属性和方法重复性, 可以使用class中一个特殊的方法constructor, 该方法称为构造函数(构造方法)
  2. 构造函数会在创建实例时执行
  3. 在构造函数中, this表示当前创建的对象
class People {
   name
   age
   gender
   constructor(name, age, gender) {
     console.log('构造函数执行了~', name, age, gender)
     this.name = name // 可以在构造函数中将参数变量赋值给实例
     this.age = age
     this.gender = gender
  }
}
const p1 = new People("张三", 10, "男") // 构造函数执行了~ 张三 10 男
console.log(p1)  

封装

  • js中的对象是用来存储属性和方法的容器,class中可通过两种封装方式来保证内部属性的安全:
  1. 将属性私有化 加#,
class Person {
   #address = '花果山' // 只能通过类或者实例方法访问
   constructor(address) {
       this.#address = address
   }
}
  1. 是通过gettersetter方法来操作属性
class Person {
    #gender 
    #name
    // getter方法,用来读取属性
    getName() {
       return this.#name
    }
    // setter方法,用来设置属性
    setName(name) {
       this.#name = name
    }
    get gender() {
        return this.#gender // gender必须要先声明 
    }
    set gender(gender) { // 必须要有参数
        this.#gender = gender
    }
}
console.log(p1.gender) // 女    //通过属性方式访问
p1.gender = '女' // 通过属性方式赋值
console.log(p1)

多态

  • JS中不会检查参数的类型,意味着任何数据都可以作为参数传递,要调用某个函数,无需指定的类型,只要对象满足条件即可,为JS提供了灵活性
class Person {
    constructor(name) {
      this.name = name
    }
  }
  
class Dog {
    constructor(name) {
      this.name = name
    }
  }
  
const person = new Person('小李')
const dog = new Dog('旺财')
console.log(person, dog)

function sayHello(obj) { // 不需要对obj的类型做判断
  // if (obj instanceof Person) {
    console.log('Hello,' + obj.name)
  // }
  }
sayHello(person)
sayHello(dog)

继承

  • 通过继承,可以在不修改一个类的情况下进行扩展,ES6中class可以用extends关键字来完成继承 当一个类继承另一个类时,就相当于将另一个类中的代码复制到当前类中。继承发生时, 被继承的类称为父类(超类), 继承的类称为子类通过继承可以减少重复的代码,并且可以在不修改一个类的前提对其进行扩展
// 定义一个Animal类
class Animal {
    constructor(name) {
        this.name = name
    }
    sayHello() {
        console.log('动物在叫')
    }
}

// 定义一个Dog
class Dog extends Animal{
    sayHello() { // 子类同名方法会覆盖父类
        console.log('汪汪叫')
    }
}

// 定义一个Cat
class Cat extends Animal {
    // 重写父类的构造函数,必须在子类的constructor中使用super
    // 将需要的参数,使用super(参数)传递给父类
    construtor(name, age) {
        super(name)
        this.age = age
    }
    sayHello() {
        // 重写父类的方法
        super.sayHello() // 调用父类方法
        console.log('喵喵喵') // 加上自己的方法
    }
}

const dog = new Dog('旺财')
const cat = new Cat('汤姆', 123)

console.log(dog)
console.log(cat)

dog.sayHello()  // 汪汪叫
cat.sayHello() // 动物再叫, 喵喵喵

总结

ES6class本质上就是ES5构造函数的语法糖,其新增的封装,多态和继承,为JS提供了数据的安全性、调用的灵活性以及创建的扩展性。 其他文章: ES5中几种继承方式及其优缺点