2017-06-05 102 views
2

我有点遗失ES6隐私类。我有这个类:什么是“私人财产”在ES6课堂上的意思?

class Whatever { 

     constructor(value) { 
      this._value = Number(value); 
     } 

     total() { 
      return this._value * 2; 
     } 
    } 

    let instance = new Whatever('1000'); 
    console.log(instance.total());  // 2000  
    console.log(instance._value );  // 1000 

我想学符号()是如何工作的,以保持私人数据(see link),阅读我试图做一下简单的例子,但似乎不是文档后有什么区别:

const _value = Symbol('value'); 

    class Whatever { 

     constructor(value) { 
      this[_value] = Number(value); 
     } 

     total() { 
      return this[_value] * 2; 
     } 
    } 


    let instance = new Whatever('1000'); 
    console.log(instance.total());  // 2000  
    console.log(instance[_value] ); // 1000 

有人能解释我在一个全面的方式,这是什么意思隐私在这种情况下,为什么我的私有化数据(使数据从类的外部unaccesible)的想法是错误的?我没有太多的OOP经验。

谢谢。

+0

它也是一样,正如链接文章所提到的:它们(两者)“*对外界有些隐藏,但不完全*”。 – Bergi

回答

1

在你的例子没有真正的区别,假设你通过不循环该类的枚举属性。

考虑以下几点:用符号命名

function MyFunction() { 
    const _private = new Symbol(); 

    this[_private] = 5; 
    this.public = 10; 
} 

const thing = new MyFunction(); 

for (let key in thing) { // prints 10 
    console.log(thing[key]); 
} 

console.log(thing.public); // prints 10 
console.log(thing._private); // undefined 

属性是不可枚举的,所以从某种意义上讲,他们是不是“暴露”。符号的另一个好处是它们可以保证创建唯一的密钥,所以不用担心密钥名称冲突。

为了简单起见,我选择用函数而不是类来说明它。对于一类,你可以做以下(这是所有关于余地“保护”的符号):

const MyClass = (function() { 
    const _value = Symbol(); 
    return class _MyClass { 
    constructor() { 
     this[_value] = 5; 
    } 
    } 
})(); 

免责声明:这不是“真”的隐私,因为还是有办法来枚举符号。我认为最大的优势是名称冲突。

+0

非常感谢,谢谢。 – Biomehanika

0

这里有一些细微的概念。

Symbol s是全球唯一的;也就是说,如果您拨打Symbol.create('somestring');两次,它将产生两个完全不同的符号。

“别人”无法以其他方式访问其键为符号**的对象属性,而无法访问该符号。在第二个示例中,该类下面的代码仍具有对该符号的词汇访问权限。但是,如果要导出类,无论是通过模块系统还是仅返回其他没有词汇访问的调用函数(即使他们知道用于标记符号的字符串),都不会出现这种情况,因为它们不能重新创建它(如上所述)。

**编辑2:正如其他人所述,包括Dr. Rauschmayer在内,“其他人”可以通过Reflect.ownKeys(object)访问包括符号在内的按键。在这个非常有意思的案例中,人们会希望对方知道他们在做什么......因此,使用符号作为关键字的整个范例仍然有助于确保关键字的非冲突命名空间(例如,如果其他人想要增加你的对象,而不会意外地覆盖任何重要的“内部”属性)。但是,100%保护不允许故意访问或修改。 (有一个在作品相关ECMAScript proposal,有趣的阅读。)

编辑:这里有一个例子

let Whatever = (function() { 
 
     const _value = Symbol('value'); 
 

 
     class Whatever { 
 

 
     constructor(value) { 
 
      this[_value] = Number(value); 
 
     } 
 

 
     total() { 
 
      return this[_value] * 2; 
 
     } 
 
     } 
 
     
 
     return Whatever; 
 
    })(); // IIFE 
 

 

 
    let instance = new Whatever('1000'); 
 
    console.log(instance.total()); // 2000  
 
    console.log(instance._value); // undefined 
 
    console.log(instance[_value]); // ReferenceError: _value is not defined

+0

编辑:添加了一个工作示例 – nikulis

+1

@le_m啊,你说得对。所以这可能是对方故意反思的情况,而不是仅仅试图阻止名称冲突。感谢您指出,我会更新我的回答。 – nikulis

+0

非常感谢,谢谢。我已经标记了另一个答案,因为两者都是有效的,但最老的是另一个答案。 – Biomehanika