ES6 类私有属性只是语法糖吗?

Eva*_*hen 6 javascript ecmascript-6 es6-class

使用 # 语法,我们现在可以在 ES6 类中创建私有属性,如下所示:

class Person {
    #name;
    constructor(name) {
        this.#name = name;
    }
    getName() { return this.#name; }
}

let ron = new Person('ron')
ron.#name // undefined
ron.getName(); // ron
Run Code Online (Sandbox Code Playgroud)

以前,在 ES5 中,私有属性很难通过以下方式“伪造”:

function Person(name) {
  var name = name;
  this.getName = function() {
    return name;
  }
}
(new Person('ron')).name // undefined
(new Person('ron')).getName() // ron
Run Code Online (Sandbox Code Playgroud)

上面的版本使用了“var”不属于 Person 实例的“this”这一事实。因此,使用“闭包”getName 的力量可以访问“名称”。然而,这样做的问题是 this.getName() 不是原型链的一部分,因此为了将 getName 添加到原型中,我们必须这样做:

Person.prototype.getName = function() { return this.getName(); }
Run Code Online (Sandbox Code Playgroud)

这很令人困惑,而且味道很难闻。

另一种选择是:(使用 ES6 符号但仍然不使用类)

function Person(name) {
  const nameSymbol = Symbol();
  this[nameSymbol] = name;
  this.getName = function() {
    return this[nameSymbol];
  }
}
Run Code Online (Sandbox Code Playgroud)

但仍然没有解决 getName 不是原型的一部分的问题。另一个问题是,使用 Object.getOwnPropertySymbols 可以访问这个“假”私有成员。

另一个 es5 选项是使用“Revleaing 模块模式”并公开一个 publicAPI,如下所示:

const myEs5Module = (function () { 
  var _name = 'yos';
  function getName() {
    return _name;
  }
  const publicAPI = { getname };
  return publicAPI;
})();
Run Code Online (Sandbox Code Playgroud)

但这不是一个类或构造函数,它更像是一个模块。

所以我想了解 ES6 类中私有属性的“#”语法是否是语法糖,并且可以为像我这样的函数爱好者以某种方式进行填充。

顺便说一句:我读了类似以下的文章: JavaScript ES6 类中的私有属性 ,但仍然感到不满意。另请注意:我不是在寻找 ES6 模块/babel 解决方案

T.J*_*der 5

ES6 类私有属性只是语法糖吗?

不。它们是对象内部工作方式的基本补充。私有字段(如它们的名称)保存在对象的新槽中,该槽在提案之前不存在,并且无法通过其他方式访问。

所以我想了解 ES6 类中私有属性的“#”语法是否是语法糖,并且可以为像我这样的函数爱好者以某种方式进行填充。

没有语法就不能使用私有属性class。(未来的提案可能会改变这一点。)相反,您必须继续做您正在做的事情(闭包解决方案),或者仅使用WeakMap您的函数有权访问由属性相关的对象作为键控的函数。

您已经完成了自己的闭包示例,因此这是Person使用该WeakMap方法而不是私有属性的类:

const Person = (() => {
    const names = new WeakMap();
    function Person(name) {
        names.set(this, name);
    }
    Person.prototype.getName = function getName() {
        return names.get(this);
    };
    return Person;
})();

let ron = new Person("ron")
console.log(ron.name);      // undefined
console.log(ron.getName()); // "ron"
Run Code Online (Sandbox Code Playgroud)