处理私有变量

在 JavaScript 中以函数作用域来处理私有变量的。当引入跨函数作用域的私有变量的时候,人们会试图为私有变量添加 _ 前缀以表示它们的私有性,然后暴露为公有变量。这个可以防止意外的引用,但是仍然无法避免命名冲突。一个更好的替代方案是使用 ES6 的 Symbol 数据类型。

Symbol 是指的一个唯一和固化的数据类型,可以被用来作为对象的属性。

以下为一个 symbol 示例

  1. const color = Symbol()
  2. function colorize(elem, state, next) {
  3. elem[color] = 'red'
  4. next()
  5. }

现在 red 只能被 color 标记的引用来读取。'red' 的私有性可以通过暴露 color 标记为不同的值来控制。当有了一定量的私有变量的时候,使用一个集中标记存储系统是一种优雅的解决方案。

  1. exports.private = {
  2. color: Symbol('color from colorize')
  3. }
  4. exports.public = {}

添加 index.js,内容如下:

  1. const symbols = require('./symbols')
  2. exports.symbols = symbols.public

存储系统可以被工程内部的所有模块所访问但是私有的部分不会暴露出去。公有部分可以被用来暴露底层的功能给外部开发人员。这样可以防止意外引用错误,因为开发人员不得不通过显式地引用相应的标记来使用变量。另外,标记引用不会像字符串那样产生冲突,所以就可以避免命名冲突。

以下总结了不同场景下的模式的使用。

1.公有变量

正常使用。

  1. function (elem, state, next) {
  2. elem.publicText = 'Hello World'
  3. next()
  4. }

2.私有变量

跨作用域变量,即项目的私有变量,应该有一个被添加到私有标记库的标记键值。

  1. exports.private = {
  2. text: Symbol('private text')
  3. }
  4. exports.pubic = {}

当需要的时候引用。

  1. const private = require('symbols').private
  2. function (elem, state, next) {
  3. elem[private.text] = 'Hello World'
  4. next()
  5. }

半私有化变量

须在公共标记表中添加底层 API 的变量的标记键值。

  1. exports.private = {
  2. text: Symbol('private text')
  3. }
  4. exports.public = {
  5. text: Symbol('exposed text')
  6. }

需要的时候加载。

  1. const exposed = require('symbols').public
  2. function (elem, state, next) {
  3. elem[exposed.text] = 'Hello World'
  4. next()
  5. }