JS中如何创建私有变量

JS中创建私有变量

1、使用闭包(Closure) 模拟私有变量

通过使用闭包,可以将私有变量封装在一个函数的作用域内,外部无法直接访问这些私有变量。闭包可以保证私有变量的封装性和安全性。

function MyClass() {
  // 私有变量
  let privateVar = 'I am private';

  // 公共方法
  this.getPrivateVar = function() {
    return privateVar;
  }

  this.setPrivateVar = function(value) {
    privateVar = value;
  }
}

const myInstance = new MyClass();
console.log(myInstance.getPrivateVar());  // "I am private"
myInstance.setPrivateVar('New Value');
console.log(myInstance.getPrivateVar());  // "New Value"
console.log(myInstance.privateVar);  // undefined (无法直接访问私有变量)

privateVar 是通过闭包实现的私有变量,外部代码无法直接访问它。
通过 getPrivateVar 和 setPrivateVar 方法可以间接访问和修改私有变量。

具体来说:

  • privateVar 是一个 局部变量,它被封闭在 MyClass 构造函数内部。
  • getPrivateVar 和 setPrivateVar 函数能够访问并操作这个局部变量,即使它们被返回并在 MyClass 构造函数外部执行。这样,privateVar 就保持了私有性,不会被外部直接访问。

闭包的特性在此体现:

  • 词法作用域:函数在定义时就会记录它所能访问的变量范围,而不仅仅是在执行时。
  • 访问私有数据:通过闭包,外部代码不能直接访问 privateVar,但可以通过公共方法(如 getPrivateVar 和 setPrivateVar)间接访问或修改它。

其中词法作用域,又叫静态作用域,变量被创建时就确定好了,而非执行阶段确定的。也就是说我们写好代码时它的作用域就确定了,JavaScript 遵循的就是词法作用域。

2、使用 ES6 Symbol(符号) 模拟私有变量

Symbol 是 ES6 引入的一个新的基本数据类型,它可以用作对象的唯一属性键,避免外部直接访问。你可以用 Symbol 来创建私有变量。

Symbol 是 在 ES6引入的一种原始数据类型。它代表了一个独一无二的、不可变的值。每个通过 Symbol() 创建的 Symbol 值都是唯一的,即使它们有相同的描述,也会被视为不同的值。

const privateVar = Symbol('privateVar');

class MyClass {
  constructor() {
    this[privateVar] = 'I am private';
  }

  getPrivateVar() {
    return this[privateVar];
  }

  setPrivateVar(value) {
    this[privateVar] = value;
  }
}

const myInstance = new MyClass();
console.log(myInstance.getPrivateVar());  // "I am private"
myInstance.setPrivateVar('New Value');
console.log(myInstance.getPrivateVar());  // "New Value"
console.log(myInstance[privateVar]);  // undefined (无法直接访问私有变量)

使用 Symbol 可以避免变量名冲突,且 privateVar 作为一个 Symbol 类型,外部无法直接访问它。

具体而言:

  • privateVar 是一个 Symbol,它作为对象 MyClass 的私有属性键。
  • this[privateVar] 存储了私有变量的值,并且外部无法直接通过 myInstance.privateVar 或 myInstance[‘privateVar’] 访问它,因为它是由Symbol 创建的,外部不知道该 Symbol 的值。
  • 通过 getPrivateVar 和 setPrivateVar 方法,外部可以间接访问或修改这个私有变量的值。

3、使用 WeakMap 模拟私有变量

WeakMap 是一个键值对集合,键是对象,值可以是任意类型。利用 WeakMap,可以将私有数据存储在一个外部的 WeakMap 中,确保数据与对象的生命周期关联,同时避免外部直接访问私有数据。

const privateVars = new WeakMap();

class MyClass {
  constructor() {
    privateVars.set(this, { privateVar: 'I am private' });
  }

  getPrivateVar() {
    return privateVars.get(this).privateVar;
  }

  setPrivateVar(value) {
    privateVars.get(this).privateVar = value;
  }
}

const myInstance = new MyClass();
console.log(myInstance.getPrivateVar());  // "I am private"
myInstance.setPrivateVar('New Value');
console.log(myInstance.getPrivateVar());  // "New Value"
console.log(privateVars.get(myInstance));  // { privateVar: 'New Value' } (直接访问 WeakMap)

privateVars 存储了对象实例的私有数据,WeakMap 会将数据与对象的生命周期关联,不会阻止垃圾回收。

4、使用 ES2022 的 # 私有字段

在 ES2022 中,JavaScript 引入了类的私有字段(#)。使用 # 前缀定义的字段在类的外部无法直接访问,这是一种新的原生私有变量实现方式。

class MyClass {
  #privateVar;  // 私有字段

  constructor() {
    this.#privateVar = 'I am private';
  }

  getPrivateVar() {
    return this.#privateVar;
  }

  setPrivateVar(value) {
    this.#privateVar = value;
  }
}

const myInstance = new MyClass();
console.log(myInstance.getPrivateVar());  // "I am private"
myInstance.setPrivateVar('New Value');
console.log(myInstance.getPrivateVar());  // "New Value"
console.log(myInstance.#privateVar);  // SyntaxError: Private field '#privateVar' must be declared in an enclosing class

#privateVar 是私有字段,外部无法访问它,只有类的方法可以访问。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值