如何在 JavaScript 中创建私有变量?
闭包、符号、弱映射、类私有字段和代理是用于在 JavaScript 中创建私有变量的一些技术。每种技术都有其优点和缺点,因此选择最适合您需求的技术至关重要。
与许多其他编程语言一样,JavaScript 具有私有和公有变量的概念。私有变量只能由属于同一作用域的代码访问和修改,而公有变量可以由任何代码访问和修改。让我们看看在 JavaScript 中创建私有变量的不同技术。
使用闭包
闭包方法是创建 JavaScript 中私有变量的一种方法。如果一个函数即使在其父函数已完成并返回后仍然可以访问其父函数作用域中定义的变量,则该函数就是一个闭包。我们可以在函数内部定义一个变量,使其成为一个私有变量,只能由该函数内部的代码访问。
示例
<html> <body> <div id="demo"></div> <script> function createPrivateVariable() { let privateVariable = "This is a private variable"; return { getValue: function () { return privateVariable; }, setValue: function (value) { privateVariable = value; }, }; } let privateVar = createPrivateVariable(); document.getElementById("demo").innerHTML = privateVar.getValue(); </script> </body> </html>
上面示例中的 createPrivateVariable 函数返回一个具有 getValue 和 setValue 方法的对象。这些方法可以检索或更改在父函数中声明的 privateVariable 的值,因为它们可以访问它。如果您尝试从函数外部访问 privateVariable,则会发生引用错误。
使用 Symbol 数据类型
使用 Symbol 数据类型是创建私有变量的第二种方法。符号可以作为属性键使用,因为它们是唯一的、非字符串的标识符。由于它们是唯一的,因此外部程序不容易访问或修改它们。
let privateVariable = Symbol(); let obj = { [privateVariable]: "This is a private variable" }; console.log(obj[privateVariable]);
示例
我们可以如下使用上述代码:
<html> <body> <div id="demo"></div> <script> let privateVar = Symbol(); let obj = { [privateVar]: "This is a private variable" }; Object.defineProperty(obj, 'getValue', { get: function() { return obj[privateVar]; } }); document.getElementById("demo").innerHTML = obj.getValue; </script> </body> </html>
在此示例中,已定义了一个名为 privateVariable 的 Symbol,并将其用作对象的属性键。由于它是一个 Symbol,因此无法使用点表示法获取属性的值,但可以使用方括号表示法通过对象访问它。
使用弱映射
弱映射可用作构造私有变量的第三种方法。JavaScript 引擎仅弱引用弱映射中的键值对,这允许您将一个对象与一个键关联。由于垃圾回收器将在没有其他对键的引用时销毁键值对,因此这使得意外地维护对私有变量的引用变得更加困难。
示例
<html> <body> <div id="demo"></div> <script> let privateVariables = new WeakMap(); let obj = {}; privateVariables.set(obj, "This is a private variable"); document.getElementById("demo").innerHTML = privateVariables.get(obj); </script> </body> </html>
在此示例中,我们创建了一个名为 privateVariables 的弱映射,用于保存对象的私有变量。一旦使用 set() 方法将对象与键关联,就可以使用 get() 方法获取私有变量。但是,私有变量只能在您拥有对对象的引用时才能访问,因此无法从创建对象的范围之外访问它。
使用面向对象的类语法
面向对象的类语法的使用也可以用于创建私有变量。JavaScript 的 class 关键字使我们能够定义类,类充当对象的模板。类可以使用变量名前面的 # 符号来定义变量以生成私有变量;这是一个实验性特性,表示一个私有变量。由于它目前没有得到广泛的支持,因此不建议在生产代码中使用此特性。
示例
<html> <body> <p id="output"></p> <script> class MyClass { #privateVariable = "This is a private variable"; getValue() { return this.#privateVariable; } setValue(value) { this.#privateVariable = value; } } let obj = new MyClass(); document.getElementById("output").innerHTML = obj.getValue(); // "This is a private variable" obj.setValue("New value"); document.getElementById("output").innerHTML = obj.getValue(); // "New value" </script> </body> </html>
在此示例中,使用私有变量 #privateVariable、getValue 和 setValue 构造了一个名为 MyClass 的类。如果类外部的方法尝试访问只能由类内部方法访问的私有变量,则会发生引用错误。
使用代理对象
最后,使用代理对象是构造私有变量的另一种选择。代理是可以用来拦截或修改其他对象行为的对象。您可以通过将对象封装在代理中来创建一个私有变量,该变量只能由拥有该代理的代码访问。
示例
<html> <body> <div id="demo"></div> <script> let privateVariable = "This is a private variable-proxy obj."; let handler = { get: function (target, name) { if (name === "privateVariable") { return privateVariable; } }, set: function (target, name, value) { if (name === "privateVariable") { privateVariable = value; } }, }; let obj = new Proxy({}, handler); document.getElementById("demo").innerHTML = obj.privateVariable; </script> </body> </html>
在此示例中,已构建了一个带有处理程序(包含 getter 和 setter 方法)的代理。这些方法可以检索或更改在代理外部定义并可以访问它的私有变量的值。但是,由于引用错误,私有变量将无法从代理外部访问。