js 实现封装
封装的概念
封装是面向对象编程的三大特性之一,用于隐藏对象的内部细节,仅暴露必要的接口。在JavaScript中,封装可以通过多种方式实现,包括使用闭包、Symbol、WeakMap以及ES6的class语法。
使用闭包实现封装
闭包是JavaScript中实现私有变量的常见方法。通过函数作用域,可以创建只能在函数内部访问的变量。
function createCounter() {
let count = 0; // 私有变量
return {
increment: function() {
count++;
},
getCount: function() {
return count;
}
};
}
const counter = createCounter();
counter.increment();
console.log(counter.getCount()); // 输出: 1
console.log(counter.count); // 输出: undefined
使用Symbol实现私有属性
Symbol是ES6引入的唯一值类型,可以用作对象的私有属性键。
const _count = Symbol('count');
class Counter {
constructor() {
this[_count] = 0;
}
increment() {
this[_count]++;
}
getCount() {
return this[_count];
}
}
const counter = new Counter();
counter.increment();
console.log(counter.getCount()); // 输出: 1
console.log(counter[_count]); // 输出: 1(但仍可通过Symbol访问)
使用WeakMap实现私有属性
WeakMap可以更好地隐藏私有属性,外部无法直接访问。
const _private = new WeakMap();
class Counter {
constructor() {
_private.set(this, { count: 0 });
}
increment() {
const data = _private.get(this);
data.count++;
}
getCount() {
return _private.get(this).count;
}
}
const counter = new Counter();
counter.increment();
console.log(counter.getCount()); // 输出: 1
console.log(counter.count); // 输出: undefined
使用ES6 class的私有字段
ES2022引入了私有字段语法,通过#前缀标识私有属性。

class Counter {
#count = 0; // 私有字段
increment() {
this.#count++;
}
getCount() {
return this.#count;
}
}
const counter = new Counter();
counter.increment();
console.log(counter.getCount()); // 输出: 1
console.log(counter.#count); // 报错: Private field '#count' must be declared in an enclosing class
封装的优势
封装的主要优势在于保护对象的内部状态,避免外部直接修改导致的不一致性。通过暴露有限的接口,可以更好地控制数据的访问和修改逻辑,提高代码的可维护性和安全性。






