【问题标题】:How to create private variables and methods inside a class ES6? [duplicate]如何在 ES6 类中创建私有变量和方法? [复制]
【发布时间】:2015-10-11 14:43:45
【问题描述】:

如何使用 ES6 类创建私有变量和方法,它们应该由同一类的公共方法访问。

class MyClass {
    constructor() {
        this.publicVar = "I am public";
        //some private Variable e.g privteVar1 = "I am Private1"; privateVar2 = "I am Private2";
        this.publicMethod = () => {
         //it should have accesses to private variables and methods
           console.log(privateVar1, privateVar2)
        }; 
        //similarly need to create some privateMethod           
    }

    render() {
         //it also should have access to the private variables
    }

}

【问题讨论】:

  • 我也检查过。但不清楚。如果有人在我给出的这个特定示例中帮助我,那就太好了。
  • 和你之前做的一模一样。或使用链接问题中的建议。另见stackoverflow.com/q/30191656/218196

标签: javascript oop variables methods ecmascript-6


【解决方案1】:

试试这个:

console.log(this[privateVar1], this[privateVar2])

这样调用您的属性[myPrivate]。这是使您的属性成为某种私有属性的方法。但是这种语法并不能提供真正的隐私。

【讨论】:

    【解决方案2】:

    只需将其设为本地变量,使用var/let/const,即可通过您在构造函数中定义的所有特权方法的闭包来使用它。顺便说一句,这与 ES5 并没有改变。

    class MyClass {
        constructor() {
            this.publicVar = "I am public";
            const privteVar1 = "I am Private1",
            const privateVar2 = "I am Private2";
            this.publicMethod = () => {
                // it has access to private variables
                console.log(privateVar1, privateVar2)
            };          
        }
    }
    

    请注意,这些变量是构造函数的本地变量,因此您无法从原型方法访问它们,因为您需要公共属性或复杂的解决方法。

    【讨论】:

    • 如果我需要在构造函数()之外访问 privateVar,即在同一类的其他方法中怎么办?在这种情况下,privateVar 是未定义的。
    • 请参考我编辑的问题,我在构造函数之外添加了 render()。我还需要访问私有变量。
    • @jrath: render 是一种原型方法,我已经评论过这些方法。在构造函数中移动它,或者从变量切换到公共属性。
    【解决方案3】:

    在 JS 中获得真正隐私的唯一方法是通过作用域,因此无法拥有一个只能在组件内部访问的 this 成员属性。在 ES6 中存储真正私有数据的最佳方式是使用 Wea​​kMap。

    const privateProp1 = new WeakMap();
    const privateProp2 = new WeakMap();
    
    class MyClass {
      constructor() {
        privateProp1.set(this, "I am Private1");
        privateProp2.set(this, "I am Private2");
    
        this.publicVar = "I am public";
        this.publicMethod = () => {
          console.log(privateProp1.get(this), privateProp2.get(this))
        };        
      }
    
      render() {
        //it also should have access to the private variables
        console.log(privateProp1.get(this));
      }
    
    }
    

    【讨论】:

    • 我并没有说它是完美的,但在我看来,这是获得真正隐私而又不会在其他地方产生成本的唯一方法。在构造函数中捕获变量是可行的,但是您需要先承担创建新函数表达式的前期成本,并且会失去类语法的许多好处。
    • 哦算了。在某处我读到weakmaps会导致去优化并在垃圾收集器上产生一些额外的、意想不到的成本,但我再也找不到那个引用了,我必须记错了。现在我唯一讨厌的是它们丑陋的语法:-/
    • 不能争论,哈哈。
    【解决方案4】:

    你可以使用Symbol这样实现它:

    var privateSymbol = Symbol('private');
    
    class SomeClass {
      constructor() {
        this.setPrivateValue('some init value');
      }
    
      setPrivateValue(value) {
        this[privateSymbol] = value;
      }
    
      getPrivateValue() {
        return this[privateValue];
      }
    }
    

    注意将前面的代码放在某个模块中,不要暴露privateSymbol

    【讨论】:

      【解决方案5】:

      正如@yibuyisheng 所注意到的,您可以使用符号来创建对属性的不可访问的引用。您也可以创建私有方法。

      var privateMethod = Symbol('private');
      
      class SomeClass {
        constructor() {
        }
      
        [privateMethod]() {
          // some private actions
        }
      
        render() {
          // call private method
          this[privateMethod]()
        }
      }
      

      符号创建一个唯一的引用,它可以用作属性名称。而这个属性或方法只能通过使用它来调用。这是可能的,因为 ES6 引入了computed properties syntax,您可以使用变量来定义动态属性。

      如果你不把这个符号暴露给别人,只有你可以调用它。

      【讨论】:

      • 没有。符号键是公共的,就像字符串属性名称一样,并且可以枚举。你无法隐藏它们。
      • 不。类方法不能按规范迭代。参见 babel-repl 示例:bit.ly/1SCI5rD
      • 我并不是说它们可以用for in 循环枚举(没有方法是,你不需要符号)。我说symbols are just as exposed as normal properties
      • 好的,你可以从外面提取它。但是您必须为此做一些特殊的技巧,并且您知道自己在做什么。 Symbol-way privates 不能偶尔访问,对于大多数用途来说似乎已经足够了。另外,在调用私有方法时,您不必使用bindapply,但是当您将方法存储在闭包内的WeakMap 中时,您必须这样做
      • 嗯,您几乎不会“意外”访问您不拥有的对象的任何属性 - 无论如何您都是故意这样做的,而这正是 private 属性试图阻止的.
      猜你喜欢
      • 2016-04-24
      • 2016-03-28
      • 2014-10-06
      • 2016-04-24
      • 2019-07-19
      • 2015-03-07
      • 1970-01-01
      • 1970-01-01
      • 2013-07-03
      相关资源
      最近更新 更多