如何将其正确绑定到 Javascript 中的 getter/setter
How to properly bind this to a getter/setter in Javascript
假设我有一个 class 将其实例的属性存储在嵌套对象中:
this.Properties = {
"Position":{
"X": 400,
"Y": 100
},
"Colour": "#007fff7f"
};
我想为每个(嵌套的)属性定义特殊的 getters/setters 以便我可以添加范围检查/自动更新实例特定 HTML 元素的属性等。当我用普通方法尝试过,我意识到我无法将范围绑定到 getters/setters:
中的参数
//(based on
//Define function prototype for binding an argument without overriding the old this:
Function.prototype.BindArgs = function(...boundArgs){
const targetFunction = this;
return function (...args) { return targetFunction.call(this, ...boundArgs, ...args); };
};
//...
{
get X(){
return this.__X__;
},
set X(Scope, Value){
this.__X__ = Value;
Scope.HTMLElement.style.left = Value + "px";
}.BindArgs(this) //This is incorrect syntax
}
上面的代码没有 运行:不是因为 BindArgs 是一个无效的原型,而是因为 . 建议使用 Object.defineProperty,所以它不起作用工作:
Object.defineProperty(this.Properties.Position, "X", {
"get": function(){
return this.__X__;
}
"set": function(Scope, Value){
this.__X__ = Value;
Scope.HTMLElement.style.left = Value + "px";
}.BindArgs(this)
});
现在,当我有一些像上面示例中那样的属性时,这会很好,但是必须对几十个属性执行此操作变得非常乏味 - 特别是对于嵌套属性。 是否有另一种更简洁的方法来定义自定义 getters/setters 并能够将参数绑定到它们? 正常的语法本来是理想的,因为它都在对象定义而不是像 Object.defineProperty 那样四处散布。显而易见的答案是使用普通函数来 get/set 值,但这样做意味着必须重构大量代码...
我建议你使用Proxies for validation。它只需要极少的代码更改,您可以一口气处理多个属性。
let validator = {
set: function(obj, prop, value) {
//in any of these cases you can return false or throw an error to refuse the new value
switch(prop) {
case "X":
Scope.HTMLElement.style.left = value + "px";
break;
case "Y":
Scope.HTMLElement.style.top = value + "px";
break;
case "Colour":
Scope.HTMLElement.style.color = value;
}
obj[prop] = value;
return true;
}
};
this.Properties.Position = new Proxy(this.Properties.Position, validator);
this.Properties = new Proxy(this.Properties, validator);
请注意,这使用了一个快捷方式(Properties
和 Properties.Position
使用相同的验证器),如果您发现您可能有 属性 名称重叠,您可能需要多个 validator
个对象。
假设我有一个 class 将其实例的属性存储在嵌套对象中:
this.Properties = {
"Position":{
"X": 400,
"Y": 100
},
"Colour": "#007fff7f"
};
我想为每个(嵌套的)属性定义特殊的 getters/setters 以便我可以添加范围检查/自动更新实例特定 HTML 元素的属性等。当我用普通方法尝试过,我意识到我无法将范围绑定到 getters/setters:
中的参数//(based on
//Define function prototype for binding an argument without overriding the old this:
Function.prototype.BindArgs = function(...boundArgs){
const targetFunction = this;
return function (...args) { return targetFunction.call(this, ...boundArgs, ...args); };
};
//...
{
get X(){
return this.__X__;
},
set X(Scope, Value){
this.__X__ = Value;
Scope.HTMLElement.style.left = Value + "px";
}.BindArgs(this) //This is incorrect syntax
}
上面的代码没有 运行:不是因为 BindArgs 是一个无效的原型,而是因为
Object.defineProperty(this.Properties.Position, "X", {
"get": function(){
return this.__X__;
}
"set": function(Scope, Value){
this.__X__ = Value;
Scope.HTMLElement.style.left = Value + "px";
}.BindArgs(this)
});
现在,当我有一些像上面示例中那样的属性时,这会很好,但是必须对几十个属性执行此操作变得非常乏味 - 特别是对于嵌套属性。 是否有另一种更简洁的方法来定义自定义 getters/setters 并能够将参数绑定到它们? 正常的语法本来是理想的,因为它都在对象定义而不是像 Object.defineProperty 那样四处散布。显而易见的答案是使用普通函数来 get/set 值,但这样做意味着必须重构大量代码...
我建议你使用Proxies for validation。它只需要极少的代码更改,您可以一口气处理多个属性。
let validator = {
set: function(obj, prop, value) {
//in any of these cases you can return false or throw an error to refuse the new value
switch(prop) {
case "X":
Scope.HTMLElement.style.left = value + "px";
break;
case "Y":
Scope.HTMLElement.style.top = value + "px";
break;
case "Colour":
Scope.HTMLElement.style.color = value;
}
obj[prop] = value;
return true;
}
};
this.Properties.Position = new Proxy(this.Properties.Position, validator);
this.Properties = new Proxy(this.Properties, validator);
请注意,这使用了一个快捷方式(Properties
和 Properties.Position
使用相同的验证器),如果您发现您可能有 属性 名称重叠,您可能需要多个 validator
个对象。