我希望用户只为对象设置特定属性,但同时该对象应该从自定义类构造。
例如
var row = new Row({
name : 'John Doe',
email : '[email protected]'
}, Schema);
row
可以有方法。但是当用户尝试设置row.password
时,他们是不允许的。
一种方法是使用
new Proxy
而不是 new Row
但这样我们就会失去在 Row
类中所做的所有很酷的事情。我希望 new Row
返回一个以 this
引用作为代理目标的代理对象。
有人对此有什么想法吗?如果您知道
mongoose
,mongoose
是如何做到的?
如果代理肯定会发生在您身上,限制设置功能的一种可能的解决方案是返回 ES6 代理实例。
默认情况下,JavaScript 中的构造函数会自动返回
this
对象,但您可以通过在 this
上实例化代理作为目标来定义并返回自定义行为。请记住,代理中的 set 方法应该返回一个布尔值。
MDN:set 方法应该返回一个布尔值。返回true表示 该任务成功了。如果 set 方法返回 false,并且 赋值发生在严格模式代码中,将会抛出 TypeError。
class Row {
constructor(entry) {
// some stuff
return new Proxy(this, {
set(target, name, value) {
let setables = ['name', 'email'];
if (!setables.includes(name)) {
throw new Error(`Cannot set the ${name} property`);
} else {
target[name] = value;
return true;
}
}
});
}
get name() {
return this._name;
}
set name(name) {
this._name = name.trim();
}
get email() {
return this._email;
}
set email(email) {
this._email = email.trim();
}
}
所以,现在不允许你根据代理设置不可设置的属性。
let row = new Row({
name : 'John Doe',
email : '[email protected]'
});
row.password = 'blahblahblah'; // Error: Cannot set the password property
也可以在 get 方法上有自定义行为。
但是,请注意并注意覆盖返回到调用上下文的引用。
注意: 示例代码已在 Node v8.1.3 和现代浏览器上进行了测试。
您可以在不使用代理的情况下完成此操作。
在类构造函数中,您可以像这样定义密码属性:
constructor(options, schema) {
this.name = options.name;
this.email = options.email;
Object.defineProperty(this, 'password', {
configurable: false, // no re-configuring this.password
enumerable: true, // this.password should show up in Object.keys(this)
value: options.password, // set the value to options.password
writable: false // no changing the value with this.password = ...
});
// whatever else you want to do with the Schema
}
Object.defineProperty()
页面上找到有关如何使用此功能的更多信息。