前端碎碎念笔记:JavaScript 对象的封装与抽象
▌这玩意是啥?
封装就像给你的钱包上拉链——钱(数据)放里面,只能通过拉链(方法)拿。
你不会直接把钞票散桌上,对吧?所以我们让外部代码也不能乱伸手进来改。
抽象呢,更像自动售货机——你只管投币、按按钮,饮料自己掉出来。
至于它怎么感应硬币、控制电机,那些复杂的逻辑都藏在机器里面。
这两个概念放一起,就是让复杂的内部逻辑“藏”起来,只留下简单好用的接口。
▌能干啥?
简单点讲:让代码更安全、更好维护。
封装可以防止外部代码乱改内部数据,比如直接把余额改成负数。 抽象可以把一堆细节打包成一个动作,比如“存钱”这件事—— 你只管 deposit(500)
,不用管它是加了多少、怎么记录日志的。
这样一来,别人动不了你的“钱包”,用起来也更安心。 以后要改逻辑,也只动内部代码,不影响别人调用的部分。
▌咋用?
在 JS 里,ES2022 以后其实挺好封装的,用 #
定义私有字段就行:
用
#
定义私有属性,比如#balance
,外面看不见、改不了。需要内部记录点事,就写私有方法,比如
#recordTransaction()
。把外部能用的操作,比如
deposit()
、withdraw()
,当成窗口。用
constructor
初始化状态,防止乱糟糟的值流进来。想快速建对象,可以用静态方法(
static
)当“工厂函数”。
比如这段代码👇(银行账户就是个很典型的封装例子):
class BankAccount {
// 私有属性#balance;#holder;#transactionHistory;constructor(initialBalance, accountHolder) {this.#balance = initialBalance;this.#holder = accountHolder;this.#transactionHistory = [];}// 私有方法#recordTransaction(type, amount) {this.#transactionHistory.push({holder: this.#holder,type,amount,balance: this.#balance,date: newDate(),});}// 公共方法deposit(amount) {if (amount > 0) {this.#balance += amount;this.#recordTransaction('存款', amount);return`${this.#holder} 存款成功,余额:${this.#balance} 元`;}return'存款金额必须大于 0';}withdraw(amount) {if (amount > 0 && amount <= this.#balance) {this.#balance -= amount;this.#recordTransaction('提款', amount);return`${this.#holder} 提款成功,余额:${this.#balance} 元`;}return'提款金额无效或余额不足';}// 只读接口getBalance() {returnthis.#balance;}getHistory() {return [...this.#transactionHistory];}static createSavingsAccount(holder) {returnnew BankAccount(0, holder);}
}
有了这套机制,外部就算想改 #balance
也改不了:
const myAccount = new BankAccount(1000, '小明');
console.log(myAccount.deposit(500)); // ✅ 小明存款成功,余额:1500 元
console.log(myAccount.#balance); // ❌ 报错:私有字段无法访问
▌记得一点
封装不是为了“藏私”,是为了“省心”—— 不让别人乱动你的变量,也不让未来的你掉坑。 写给人看的代码,也得替自己留点活路。
#JavaScript #面向对象 #封装与抽象 #前端笔记 #代码碎碎念 #ES6+