如何在Node.js 12中使用私有类字段?

时间:2019-08-29 10:41:32

标签: javascript node.js

在当前版本的 nodejs 12.x.x中,我们可以用private表示法声明#some_varible类字段。 #表示法将使该特定类的变量成为私有字段。

class Foo {
  #some_varible = 10;
}

我有以下问题:

  • 如何使用此变量?
  • 在生产应用中使用此类表示法声明私有类字段是否安全?
  • 当某些类字段声明为私有时,它如何在后台(在nodejs中)工作?

1 个答案:

答案 0 :(得分:3)

  

如何使用此变量?

您可以将其用作访问器属性的备用字段:

class Foo {
  #some_variable = 10;
  
  get some_variable () {
    console.log('getting some_variable');
    return this.#some_variable;
  }
  
  set some_variable (value) {
    console.log('setting some_variable');
    this.#some_variable = value;
  }
}

let bar = new Foo();

console.log(bar.some_variable);
console.log(bar.some_variable = 42);

或者您可以像普通属性一样使用它,主要区别在于,由于它是私有的,因此只能在class { ... }范围内访问,并且该属性的前缀为{{1} }。

还请注意,#this.#some_variable 不相同,后者this['#some_variable']是指字符串属性,而不是私有字段。

  

在生产应用中使用此类表示法声明私有类字段是否安全?

答案是这取决于

使用客户端JavaScript,您无法控制执行环境,但是可以使用Babel plugins将新的语言功能(例如,私有类字段)转换为功能等效项,仅依赖于旧语言规范中的语法。

在Node.js中,您可以控制执行环境,因此要使用新的语言功能,只需确保您使用的是a version that supports the syntax

  

当某些类字段声明为私有时,它如何在后台(在nodejs中)工作?

V8实施

私人字段使用块作用域symbols,它们从反射方法Object.getOwnPropertySymbols()进入黑名单。

native implementation

这是模拟此实现的转换后的类的样子:

let Foo;

{
  const some_variable = Symbol('#some_variable');

  {
    const getOwnPropertySymbolsImpl = Object.getOwnPropertySymbols;
    Object.getOwnPropertySymbols = function getOwnPropertySymbols () {
      return getOwnPropertySymbolsImpl.apply(this, arguments)
        .filter(symbol => symbol !== some_variable);
    };
  }

  Foo = class Foo {
    [some_variable] = 10;
  };
}

let bar = new Foo();
console.log(bar);

这会产生与本地实现非常相似的输出:

polyfill implementation


Babel实施

@babel/plugin-proposal-class-properties

私有字段存储为WeakMap,其中每个条目都是类实例键及其各自的私有字段property descriptor的值。

以下是Babel如何转换我们一直用作示例的类:

class Foo {
  constructor() {
    _some_variable.set(this, {
      writable: true,
      value: 10
    });
  }
}

var _some_variable = new WeakMap();

请注意,尽管_some_variable在此处没有块作用域,但Babel将确保转换后的输出中的名称不会与该范围内的任何可见名称相冲突,因此从pre-内无法访问该弱映射。编译的源代码。