告别随意改属性!用 ES6 Class 实现数据封装

126 阅读2分钟

JS 封装与私有属性:用 class 实现数据安全

在面向对象编程(OOP)中,封装是核心概念之一。它的目标就是:

保证对象内部数据的安全性,避免被外部随意修改。

在 JavaScript 中,我们可以使用 类(class)+ 私有属性(#开头) 来实现封装。


私有属性的语法

class 中,使用 # 开头的变量表示私有属性
这些属性只能在类的内部访问,外部无法直接修改或读取。

class Person {
  // 定义私有属性
  #name
  #age
  #gender

  constructor(name, age, gender) {
    this.#name = name
    this.#age = age
    this.#gender = gender
  }
}

提供安全的访问方式

为了让外部能够“间接”访问私有数据,我们通常提供 gettersetter 方法。
这就是 封装的精髓 —— 不直接暴露属性,而是通过方法来做校验安全访问

class Person {
  #name
  #age
  #gender

  constructor(name, age, gender) {
    this.#name = name
    this.#age = age
    this.#gender = gender
  }

  // getter:安全获取数据
  get age() {
    return this.#age
  }

  // setter:安全修改数据
  set age(value) {
    if (value > 0 && value <= 120) {
      this.#age = value
    } else {
      console.warn('年龄不合法!')
    }
  }

  // 普通方法
  sayHello() {
    console.log(`大家好,我是${this.#name},今年${this.#age}岁,性别:${this.#gender}`)
  }
}

const p1 = new Person('Linxi', 18, '女')
p1.sayHello()

console.log(p1.age) // 18
p1.age = 200        // 警告:年龄不合法!

常见错误点

  1. 私有属性必须先声明再使用

    class A {
      #x // 必须先写在类里
      constructor(x) {
        this.#x = x
      }
    }
    
  2. 外部不能直接访问私有属性

    const a = new A(10)
    console.log(a.#x) //  语法错误,直接访问会报错
    
  3. getter / setter 建议简化命名
    不要写 get getAge() 这种,直接 get age() 即可,使用时更自然:

    console.log(p1.age) // getter
    p1.age = 20         // setter
    

小结

  • #属性名 → 声明私有属性,只能在类内部使用
  • getset → 提供对私有属性的安全访问
  • 封装的本质 → 限制数据的访问范围 + 提供安全的读写方式

通过这种方式,我们就能让对象的数据更安全,也让代码更具扩展性。