此方法是否在 Javascript 中提供完全私有的属性?
Does this method give completely private properties in Javascript?
编辑:它不起作用
感谢@loganfsmyth
基于此 Private properties in JavaScript ES6 classes,使用 Symbol() 似乎是最好的方法,因为:
- 方法在原型上
- 简洁的语法
- 几乎是私人的
但只有 "almost",因为我们可以使用 Object.getOwnPropertySymbols() 来遍历属性。现在我已经稍微修正了这个方法,使用闭包。
const Person = (function () {
const myKey = {};
const lock = Symbol();
return class {
constructor(name, age) {
const data = { name, age }; // PRIVATE PROPERTIES GO INSIDE DATA
this[lock] = key => key === myKey ? data : null; // Lock check
}
info() {
const data = this[lock](myKey); // Open lock for every method
return `Name: ${data.name}, age: ${data.age}`;
}
}
})()
// Extending
const Student = (function () {
const myKey = {};
const lock = Symbol();
return class extends Person {
constructor(name, age, school) {
super(name, age);
const data = { school }; // PRIVATE PROPERTIES GO INSIDE DATA
this[lock] = key => key === myKey ? data : null; // Lock check
}
info() {
const data = this[lock](myKey); // Open lock for every method
return `${super.info()}, school: ${data.school}`;
}
}
})()
var ryan = new Student('Ryan Vu', 25, 'Seneca College');
var jane = new Student('Jane Vu', 29, 'Queen University');
console.log(ryan.info());
console.log(jane.info());
//Name: Ryan Vu, age: 25, school: Seneca College
//Name: Jane Vu, age: 29, school: Queen University
它确实有一些缺点,比如你必须为每个方法调用锁定函数,但总的来说,如果你的目标是拥有一个完全私有的 class,我认为这是一个好方法,并且它也遵循原型链的规则。我在这里发帖是因为我不确定我的想法是否正确,我没有编程经验。请纠正我。谢谢。
编辑 - 简要说明:所有方法都通过锁访问私有数据。虽然外面可以看到锁,但是只有方法和锁本身才能看到钥匙。
这种方法不起作用,因为您仍然可以使用自己的版本更新 lock
函数,并使用该版本获取密钥,例如
var person = new Person();
var lock = Object.getOwnPropertySymbols(person)[0];
var key = (function(){
let key = null;
let origLock = person[lock];
person[lock] = function(k){ key = k; return origLock.apply(this, arguments); };
person.info();
return key;
})();
const data = person[lock](key);
我认为 的工作是使 属性 不可配置,从而改变
this[lock] = key => key === myKey ? data : null;
到
Object.defineProperty(this, lock, {
value: key => key === myKey ? data : null,
configurable: false, // this is the default, here for clarity, but omittable.
});
这可以防止任何东西重新分配 [lock]
属性。
就是说,到这里为止,您基本上已经实现了 WeakMap polyfill。你也可以考虑做
const Person = (function () {
// Pull these methods off the prototype so that malicious code can't
// reassign them to get data about the private accesses.
const { set, get } = WeakMap.prototype;
const storage = new WeakMap();
return class {
constructor(name, age) {
set.call(storage, this, { name, age }); // PRIVATE PROPERTIES GO INSIDE DATA
}
info() {
const data = get.call(storage, this); // Open lock for every method
return `Name: ${data.name}, age: ${data.age}`;
}
}
})();
var person = new Person();
console.log(person);
编辑:它不起作用
感谢@loganfsmyth
基于此 Private properties in JavaScript ES6 classes,使用 Symbol() 似乎是最好的方法,因为:
- 方法在原型上
- 简洁的语法
- 几乎是私人的
但只有 "almost",因为我们可以使用 Object.getOwnPropertySymbols() 来遍历属性。现在我已经稍微修正了这个方法,使用闭包。
const Person = (function () {
const myKey = {};
const lock = Symbol();
return class {
constructor(name, age) {
const data = { name, age }; // PRIVATE PROPERTIES GO INSIDE DATA
this[lock] = key => key === myKey ? data : null; // Lock check
}
info() {
const data = this[lock](myKey); // Open lock for every method
return `Name: ${data.name}, age: ${data.age}`;
}
}
})()
// Extending
const Student = (function () {
const myKey = {};
const lock = Symbol();
return class extends Person {
constructor(name, age, school) {
super(name, age);
const data = { school }; // PRIVATE PROPERTIES GO INSIDE DATA
this[lock] = key => key === myKey ? data : null; // Lock check
}
info() {
const data = this[lock](myKey); // Open lock for every method
return `${super.info()}, school: ${data.school}`;
}
}
})()
var ryan = new Student('Ryan Vu', 25, 'Seneca College');
var jane = new Student('Jane Vu', 29, 'Queen University');
console.log(ryan.info());
console.log(jane.info());
//Name: Ryan Vu, age: 25, school: Seneca College
//Name: Jane Vu, age: 29, school: Queen University
它确实有一些缺点,比如你必须为每个方法调用锁定函数,但总的来说,如果你的目标是拥有一个完全私有的 class,我认为这是一个好方法,并且它也遵循原型链的规则。我在这里发帖是因为我不确定我的想法是否正确,我没有编程经验。请纠正我。谢谢。
编辑 - 简要说明:所有方法都通过锁访问私有数据。虽然外面可以看到锁,但是只有方法和锁本身才能看到钥匙。
这种方法不起作用,因为您仍然可以使用自己的版本更新 lock
函数,并使用该版本获取密钥,例如
var person = new Person();
var lock = Object.getOwnPropertySymbols(person)[0];
var key = (function(){
let key = null;
let origLock = person[lock];
person[lock] = function(k){ key = k; return origLock.apply(this, arguments); };
person.info();
return key;
})();
const data = person[lock](key);
我认为 的工作是使 属性 不可配置,从而改变
this[lock] = key => key === myKey ? data : null;
到
Object.defineProperty(this, lock, {
value: key => key === myKey ? data : null,
configurable: false, // this is the default, here for clarity, but omittable.
});
这可以防止任何东西重新分配 [lock]
属性。
就是说,到这里为止,您基本上已经实现了 WeakMap polyfill。你也可以考虑做
const Person = (function () {
// Pull these methods off the prototype so that malicious code can't
// reassign them to get data about the private accesses.
const { set, get } = WeakMap.prototype;
const storage = new WeakMap();
return class {
constructor(name, age) {
set.call(storage, this, { name, age }); // PRIVATE PROPERTIES GO INSIDE DATA
}
info() {
const data = get.call(storage, this); // Open lock for every method
return `Name: ${data.name}, age: ${data.age}`;
}
}
})();
var person = new Person();
console.log(person);