在 ES6 类中具有私有属性和方法 [重复]

Posted

技术标签:

【中文标题】在 ES6 类中具有私有属性和方法 [重复]【英文标题】:Have private properties & methods in ES6 classes [duplicate] 【发布时间】:2016-04-24 14:48:02 【问题描述】:

我只是在尝试 ES6,并想将用常规 javascript 编写的部分代码重写为 ES6。现在,我在尝试重写 ES6 类中的私有属性和方法时遇到了困难。似乎 ES6 中的类没有明确提供任何具有私有数据或方法的东西。

另外,我检查了这个线程:Private properties in JavaScript ES6 classes,发现我们可以使用WeakMap 来存储私人数据。这有点奇怪,但它仍然可以解决。我确实设法将它用于私人数据。

但是私有方法呢?在 ES6 类中使用私有方法(甚至是受保护的方法)的推荐方法是什么?

如果有人能向我展示一种使用 ES6 类和私有方法重写这部分代码的干净方法,我将不胜感激。

谢谢。

这是普通的旧 javascript 代码:

function Deferred() 

    // Private data
    var isPending;
    var handlers = 
        resolve: [],
        reject: [],
        notify: []
    ;

    // Initialize the instance
    init();

    function init() 
        isPending = true;
        this.promise = new Promise(this);
    

    // Public methods
    this.resolve = function(value) 
        trigger('resolve', value);
    ;

    this.reject = function(reason) 
        trigger('reject', reason);
    ;

    this.notify = function(value) 
        trigger('notify', value);
    ;

    this.on = function(event, handler) 
        ...
    ;

    // Private method
    function trigger (event, params) 
        ...
    

【问题讨论】:

MDN:Classes文章中应该有足够的信息。 【参考方案1】:

似乎 ES6 中的类没有明确提供任何具有私有数据或方法的东西。

正确。 class 语法适用于具有原型方法的普通类。如果你想要私有变量,你可以像往常一样把它们放在构造函数中:

class Deferred 
    constructor() 
        // initialise private data
        var isPending = true;
        var handlers = 
            resolve: [],
            reject: [],
            notify: []
        ;

        // Private method
        function trigger(event, params) 
            ...
        

        // initialise public properties
        this.promise = new Promise(this);

        // and create privileged methods
        this.resolve = trigger.bind(null, 'resolve');
        this.reject = trigger.bind(null, 'reject');
        this.notify = trigger.bind(null, 'notify');

        this.on = function(event, handler) 
            …
        ;
    

【讨论】:

似乎没问题。但是,如果这是唯一的方法,我认为保留旧的 javascript function() 样式会更“干净”。因为在这种情况下,我们对 ES6 类无能为力。 嗯,我希望你至少有一些原型方法,不是吗? 这里的“私有”东西只在构造函数中可用。您必须放弃使用类 getter 和 setter 以及类方法才能使其正常工作(或者至少那些涉及所谓的“私有”成员的方法)。在这种情况下,您将被简化为单个对象生成函数,这与“传统”类函数没有任何不同。 @Sahuagin 符号不是私有的。它们与带有下划线前缀的属性名称一样好。是的,在 JS 中实现“隐私”还有其他方法,但这里 OP 专门要求提供与他的 ES5 代码等效的东西。 嗯,是的,语法是不同的,它们对通常的 (ES5) 自省方法是隐藏的,但它们并不是真正不可访问且不比其他属性更安全。【参考方案2】:

您可以使用符号来赋予某种私有成员。

const KEY = Symbol( 'key' )
const ANOTHER = Symbol( 'another' )

class Foo 
  constructor() 
    this[ KEY ] = 'private'
  

  say() 
    console.log( this[ KEY ] )
  

  [ ANOTHER ] = 'transpilation required'

使用class field 将第二个符号添加到类中,这只是在提议中,需要转译才能在任何地方工作,但其余的在节点和新浏览器中工作。

【讨论】:

这是一种奇怪的语法,感觉有点像黑客,但它确实有效,基本上相当于真正的私人成员。 我虽然这也是个好主意,但该物业并不是真正的私人财产。您无法使用instance.key 访问该值,但您仍然可以使用instance[Object.getOwnPropertySymbols(instance).filter(s => s.toString().replace(/^Symbol\(([^)]+)\)$/, '$1') === 'key')[0]] 好吧,你可以这样做......

以上是关于在 ES6 类中具有私有属性和方法 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ES6 类中定义静态属性 [重复]

Es6 的类(class)

es6中类中的静态属性实例属性静态方法实例方法的个人理解

如何访问派生类中的私有集属性[重复]

ES6入门六:class的基本语法继承私有与静态属性修饰器

JS ES6类中定义的属性 为啥不在原型里