我在课堂上隐藏了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
我正在尝试学习Symbol()如何保持数据私有(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
有人可以全面地解释我,隐私在这个案例中意味着什么,以及为什么我的数据私有化(使数据无法从类外获得)的想法是错误的?我对OOP没有多少经验。
谢谢。
答案 0 :(得分: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;
}
}
})();
免责声明:它不是" true"隐私,因为仍然有方法来枚举符号。我认为最大的优势在于名称冲突。
答案 1 :(得分:0)
这里有一些微妙的概念。
Symbol
是全球唯一的;也就是说,如果你两次调用Symbol.create('somestring');
,它将产生两个完全不同的符号。
没有办法让其他人"访问其键是符号**的对象属性,而无法以其他方式访问该符号。在第二个示例中,类下面的代码仍然具有对符号的词汇访问。但是,如果要导出您的类,无论是通过模块系统还是仅返回到其他没有词汇访问的其他调用函数,即使他们知道您用来标记符号的字符串,也不会出现这种情况,因为他们可以&#39重新创建它(如上所述)。
**编辑2:正如其他人所说,包括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