如何使属性私有化?

我们在开发过程中,有时候期望使一个属性只有内部可以访问,而外部无法访问。本章我们就探寻一下如何使一个属性私有化

命名约定

约定私有属性的命名为一个带有前缀的属性,通常使用下划线_。一起看一下下面的代码:

class MyClass {
  _name = "ray";
  getName = () => {
    return this._name;
  };
}
const myClass = new MyClass();
console.log(myClass._name);
// 输出 ray
console.log(myClass.getName());
// 输出 ray

从上面的代码可以看出,虽然这并没有真正保护属性不被访问,但是表示这是一个私有属性,开发人员应该尽量避免直接访问它。

闭包

使用闭包来创建一个私有变量,它只能在闭包内部访问。如下:

class MyClass {
  getName = () => {
    const _name = "ray";
    return _name;
  };
}
const myClass = new MyClass();
console.log(myClass._name);
// 输出 undefined
console.log(myClass.getName());
// 输出 ray

从上面代码可以看出,通过在类中创建一个私有变量,并将其作为公有方法的一部分返回,可以实现私有属性的效果。这样可以确保在闭包外部无法直接访问私有变量,只能通过公有方法来访问它。因此,使用闭包可以实现一种模拟私有属性的机制。

需要注意的是,在JavaScript中,闭包可以创建一个独立的作用域,其中的变量在方法执行结束后仍然可以访问。换句话说,闭包会导致变量一直存在于内存中,即使它们已经不再需要,可能会造成内存泄漏,导致性能下降

Symbol

使用Symbol创建一个唯一的标识符来模拟私有属性。由于 Symbol 是唯一的,因此开发人员无法直接获取该属性

const nameSymbol = Symbol("name");
class MyClass {
  [nameSymbol] = "ray";
  getName = () => {
    return this[nameSymbol];
  };
}
const myClass = new MyClass();
console.log(myClass.name);
// 输出 undefined
console.log(myClass.getName());
// 输出 ray

从上面的代码可以看出,我们使用getName可以拿到这个私有属性,当我们直接获取时拿到的是一个undefined。这虽然实现了我们的预期,但是如果我们拿到nameSymbol的引用,我们依然是可以获取到这个属性

console.log(myClass[nameSymbol]);
// 输出 ray

当我们不知道一个Symbol属性的引用时,我们依然可以通过Object.getOwnPropertySymbols获取到该引用

// a.js
const nameSymbol = Symbol("name");
export class MyClass {
  [nameSymbol] = "ray";
  getName = () => {
    return this[nameSymbol];
  };
}
// b.js
import { MyClass } from "./a.js";
var myClass = new MyClass();
var symbols = Object.getOwnPropertySymbols(myClass);
console.log(symbols);
// 输出 [ Symbol(name) ]
const name = symbols[0];
console.log(myClass[name]);
// 输出 ray

私有属性#

为了解决以上实现私有属性所存在的问题,在es12中引入了新的语法,使用增加哈希前缀#的方法来定义私有类字段

class MyClass {
  #name = "ray";
  getName = () => {
    return this.#name;
  };
}
const myClass = new MyClass();
console.log(myClass.getName());
// 输出 ray
console.log(myClass.#name);
console.log(myClass.#name);
/**
 * 编辑器抛出异常
 * 属性 "#name" 在类 "MyClass" 外部不可访问,因为它具有专用标识符。
 */

参考文档

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值