JavaScript 中创建私有成员的多种实现方案
本文深入探讨JavaScript中实现私有成员的五种主要方式,包括利用闭包封装、ES6 Class外部定义、ES2020提案的#前缀语法、基于WeakMap的数据存储以及TypeScript的private关键字。通过对比各方案的代码结构、性能表现及适用场景,帮助开发者根据实际需求选择最合适的私有化实现策略,提升代码的安全性与可维护性。
前言:
在面向对象编程语言中,private 关键字作为访问修饰符,限制属性和方法仅在声明类内部可见。这种机制有助于隐藏底层实现逻辑,防止外部直接交互,从而增强封装性。
然而,JavaScript 原生并未提供 private 保留字。不过,随着 ES2020 试验草案的推进,JavaScript 引入了以 # 为前缀的新语法来定义类私有成员。尽管语法较为特殊,但这为创建真正的私有属性和方法提供了官方支持。下文将详细介绍几种在 JavaScript 中实现私有化的可行方案。
1.使用闭包
闭包是实现私有属性和方法封装的经典手段。通过利用闭包对外部函数变量的访问特性,可以隐藏内部状态,仅暴露必要的接口。
参考以下代码片段:
function MyProfile() {
const myTitle = "DevPoint";
return {
getTitle: function () {
return myTitle;
},
};
}
const myProfile = MyProfile();
console.log(myProfile.getTitle()); // DevPoint
该模式可转化为将顶层自调用函数(IIFE)的返回值赋值给变量,并通过返回对象公开部分内部函数,从而实现私有化控制。
const ButtonCreator = (function () {
const properties = {
width: 100,
height: 50,
};
const getWidth = () => properties.width;
const getHeight = () => properties.height;
const setWidth = (width) => (properties.width = width);
const setHeight = (height) => (properties.height = height);
return function (width, height) {
properties.width = width;
properties.height = height;
return {
getWidth,
getHeight,
setWidth,
setHeight,
};
};
})();
const button = new ButtonCreator(600, 360);
console.log(button.getHeight()); // 360
2.使用 ES6 类
为了更贴近面向对象编程(OOP)风格,可以利用 ES6 引入的 class 关键字。若需实现私有化,可将属性和方法定义在类外部,通过闭包或共享对象进行隔离。
基于上述 ButtonCreator 示例,使用 class 进行重构的代码如下:
const properties = {
width: 100,
height: 50,
};
class ButtonCreator {
constructor(width, height) {
properties.width = width;
properties.height = height;
}
getWidth = () => properties.width;
getHeight = () => properties.height;
setWidth = (width) => (properties.width = width);
setHeight = (height) => (properties.height = height);
}
const button = new ButtonCreator(600, 360);
console.log(button.getHeight()); // 360
假设属性为公共状态,但希望在私有方法中访问它们,且方法上下文需指向 ButtonCreator,可通过以下方式实现:
const privates = {
calculateWidth() {
return this.width;
},
};
class ButtonCreator {
constructor(width, height) {
this.width = width;
this.height = height;
}
getWidth = () => privates.calculateWidth.call(this);
getHeight = () => this.height;
setWidth = (width) => (this.width = width);
setHeight = (height) => (this.height = height);
}
const button = new ButtonCreator(600, 360);
console.log(button.getHeight()); // 360
上述代码调用了 Function.prototype.call,用于以指定上下文执行函数。示例中,使用了 ButtonCreator 类的上下文环境。
若私有函数需要接收参数,可将其作为附加参数传递给调用函数:
const privates = {
calculateWidth(percent) {
return this.width * percent;
},
};
class ButtonCreator {
constructor(width, height) {
this.width = width;
this.height = height;
}
getWidth = () => privates.calculateWidth.call(this, 0.1);
getHeight = () => this.height;
setWidth = (width) => (this.width = width);
setHeight = (height) => (this.height = height);
}
const button = new ButtonCreator(600, 360);
console.log(button.getWidth()); // 60
3.使用 ES2020 提案
该方案仍处于 ES2020 试验草案阶段,引入了以 # 为前缀的私有方法或属性定义语法。虽然语法形式独特,但这是目前最接近原生私有成员的实现方式。
class ButtonCreator {
#width;
#height;
constructor(width, height) {
this.#width = width;
this.#height = height;
}
// 私有方法
#calculateWidth() {
return this.#width;
}
getWidth = () => this.#calculateWidth();
getHeight = () => this.#height;
setWidth = (width) => (this.#width = width);
setHeight = (height) => (this.#height = height);
}
const button = new ButtonCreator(600, 360);
console.log(button.width); // undefined
console.log(button.getWidth()); // 600
4.使用 WeakMap
此方法基于闭包思路,利用作用域变量创建私有 WeakMap,再通过 WeakMap 检索关联的私有数据。相比单纯的作用域变量方法,这种方式性能更优,因为所有实例可共享同一个 WeakMap,无需为每个实例重新创建方法逻辑。
const ButtonCreator = (function () {
const privateProps = new WeakMap();
class ButtonCreator {
constructor(width, height, name) {
this.name = name; // 公共属性
privateProps.set(this, {
width, // 私有属性
height, // 私有属性
calculateWidth: () => privateProps.get(this).width, // 私有方法
});
}
getWidth = () => privateProps.get(this).calculateWidth();
getHeight = () => privateProps.get(this).height;
}
return ButtonCreator;
})();
const button = new ButtonCreator(600, 360);
console.log(button.width); // undefined
console.log(button.getWidth()); // 600
然而,这种方式在定义私有方法时略显繁琐。
5.使用 TypeScript
可以将 TypeScript 视为 JavaScript 的一种扩展风格。借助 private 关键字,能够从面向对象语言中真正还原私有成员的功能,提供编译时的类型检查和访问控制。
class ButtonCreator {
private width: number;
private height: number;
constructor(width: number, height: number) {
this.width = width;
this.height = height;
}
private calculateWidth() {
return this.width;
}
public getWidth() {
return this.calculateWidth();
}
public getHeight() {
return this.height;
}
}
const button = new ButtonCreator(600, 360);
console.log(button.getWidth()); // 600
console.log(button.width); // error TS2341: Property 'width' is private and only accessible within class 'ButtonCreator'.
总结:
本文介绍了 JavaScript 中创建私有成员的多种实现方式。如需了解更多相关内容,请查阅本站过往文章或继续浏览后续系列。感谢大家的支持!
JS动态构建复杂嵌套JSON对象的方法
2026-11-05 15:41:52
JS负数取余为什么是负数?详解余数与模运算区别
2026-11-05 13:34:41
JS 解压出现乱码或报错怎么解决?
2026-11-05 12:32:38
JS 中 startsWith、indexOf 与正则判断字符串前缀的对比
2026-11-04 22:19:43
JS解析Excel后怎么将数据转换为JSON格式
2026-11-04 20:58:28








