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

Are ES6 class private properties just syntactic sugar?

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

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

let ron = new Person('ron')
ron.#name // undefined
ron.getName(); // ron

以前,在ES5中,私有属性很难'faked'通过以下方式:

function Person(name) {
  var name = name;
  this.getName = function() {
    return name;
  }
}
(new Person('ron')).name // undefined
(new Person('ron')).getName() // ron

以上版本使用了 'var' 不属于 Person 实例的 'this' 这一事实。 因此,使用 'closure' 的强大功能,getName 可以访问 'name'。 但是,问题是 this.getName() 不是原型链的一部分 所以为了将 getName 添加到原型中,我们必须这样做:

Person.prototype.getName = function() { return this.getName(); }

这很混乱,而且闻起来很难闻。

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

function Person(name) {
  const nameSymbol = Symbol();
  this[nameSymbol] = name;
  this.getName = function() {
    return this[nameSymbol];
  }
}

但还是没有解决getName不是原型的一部分的问题。另一个问题是使用 Object.getOwnPropertySymbols,这个 'fake' 私有成员是可访问的。

另一个 es5 选项是使用 'Revleaing module pattern' 并像这样公开一个 publicAPI:

const myEs5Module = (function () { 
  var _name = 'yos';
  function getName() {
    return _name;
  }
  const publicAPI = { getname };
  return publicAPI;
})();

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

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

顺便说一句:我阅读了如下帖子: Private properties in JavaScript ES6 classes 并且仍然感到不满意。 另请注意:我不是在寻找 ES6 模块/babel 解决方案

Are ES6 class private properties just syntactic sugar?

没有。它们是对对象如何在内部级别工作的基本补充。 Private fields(正如它们的名称)保存在提案之前不存在的对象中的新插槽中,并且无法通过其他方式访问。

So I would like to understand if '#' syntax for private properties in ES6 classes is syntactic sugar and can be polyfilled in some way for function lovers like myself.

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

您已经完成了自己的闭包示例,所以这里是您的 Person class 使用 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"