如何在Node.js 12中使用私有类字段? [英] How to use private class fields in nodejs 12?

查看:63
本文介绍了如何在Node.js 12中使用私有类字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在当前版本的 nodejs ie 12.xx 中,我们可以通过 #some_varible 表示法.#表示法将使该特定类的变量成为私有字段.

  Foo类{#some_varible = 10;} 

我有以下问题:

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

解决方案

如何使用此变量?

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

  class Foo {#some_variable = 10;得到some_variable(){console.log('geting some_variable');返回这个.#some_variable;}设置some_variable(值){console.log('setting some_variable');#some_variable =值;}}let bar = new Foo();console.log(bar.some_variable);console.log(bar.some_variable = 42);  

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

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

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

答案是这取决于.

使用客户端JavaScript,您无法控制执行环境,但是可以使用

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

 让Foo;{const some_variable = Symbol('#some_variable');{const getOwnPropertySymbolsImpl = Object.getOwnPropertySymbols;Object.getOwnPropertySymbols =函数getOwnPropertySymbols(){返回getOwnPropertySymbolsImpl.apply(this,arguments).filter(symbol => symbol!== some_variable);};}Foo =类Foo {[some_variable] = 10;};}let bar = new Foo();console.log(bar);  

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


Babel实施

<代码> @ babel/plugin-proposal-class-properties

私人字段存储为 WeakMap ,其中每个条目都是一个类实例键及其相应的私有字段 class Foo {Constructor(){_some_variable.set(this,{可写:是的,价值:10});}}var _some_variable = new WeakMap();

请注意,尽管此处未对 _some_variable 进行块作用域管理,但Babel将确保转换后的输出中的名称不会与该范围内的任何可见名称冲突,因此从内部无法访问弱映射预编译的源代码.

In the current release of nodejs i.e. 12.x.x, we can declare private class fields by the #some_varible notation. The # notation would make the variable private field for that particular class.

class Foo {
  #some_varible = 10;
}

I have the following Questions:

  • How to use this variable?
  • Is it safe to use such notations in a production app for declaring private class fields?
  • How does it work in background (in nodejs), when some class field is declared private?

解决方案

How to use this variable?

You can use it as a backing field for an accessor property:

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);

Or you can use it like a normal property, the main difference being that it can only be accessed from within the class { ... } scope, since it is private, and that the property is prefixed with a #.

Also note that this.#some_variable is not the same as this['#some_variable'], the latter of which refers to the string property, not the private field.

Is it safe to use such notations in a production app for declaring private class fields?

The answer is it depends.

With client-side JavaScript, you have no control over the executing environment, but you can transform new language features such as private class fields into functional equivalents relying only on syntax from older language specifications using Babel plugins.

In Node.js, you do have control over the executing environment, so to use new language features, just ensure you're using a version that supports the syntax.

How does it work in background (in nodejs), when some class field is declared private?

V8 implementation

Private fields use block-scoped symbols which are blacklisted from the reflection method Object.getOwnPropertySymbols().

Here's what a transformed class emulating this implementation might look like:

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);

This produces a very similar-looking output to the native implementation:


Babel implementation

@babel/plugin-proposal-class-properties

Private fields are stored as a WeakMap where each entry is a class instance key and its respective private field property descriptor value.

Here's how Babel transforms the class we've been using as an example:

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

var _some_variable = new WeakMap();

Note that while _some_variable is not block-scoped here, Babel will ensure that the name in the transformed output does not collide with any visible names in that scope, so the weak map is inaccessible from within the pre-compiled source.

这篇关于如何在Node.js 12中使用私有类字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆