我正在将我的模型实体转换为Typescript(使用ajax调用填充它们)。我希望每个人都能为我的实体中的每个属性设置一个基本的getter和setter:
entity.setProductID("2r3e4r4t5y6t5y6") and entity.getProductID()
目前,我正在为类
中的每个属性定义这些方法 /**
*@name "productID"
*@ormtype "string"
*@length "32"
*@fieldtype "id"
*@generator "uuid"
*@unsavedvalue ""
*/
private productID: string;
getProductID():string { return this.productID; }
setProductID(productID:string) { this.productID = productID; }
但是我每个实体和150个实体大约有30到80个属性,因此代码对getter和setter定义有点冗长。
为了解决这个问题,我希望使用装饰器@generateGetterAndSetter,我可以用它来装饰每个属性,为我动态生成getter和setter。看起来像:
@generateGetterAndSetter
private productID: string;
为了实现这一点,我定义了装饰器并将其添加到我的模块中:
/** decorate the property to attach a getter and setter */
function generateGetterAndSetter(target: any, key: string) {
// property value
var _val = this[key];
// property getter
var getMethodName = 'get' + key.charAt(0).toUpperCase() + key.slice(1);
var setMethodName = 'set' + key.charAt(0).toUpperCase() + key.slice(1);
/** Build the getter and setter functions dynamically */
var getter = new Function("return function " + getMethodName + "(){ return _val;}")();
var setter = new Function("return function " + setMethodName + "(newVal){ _val = newVal;}")();
target[getMethodName] = getter;
target[setMethodName] = setter;
Object.defineProperty(target, key, {
get: getter,
set: setter,
enumerable: true,
configurable: true
});
}//<--end generateGetterAndSetterDefinition
从上面的代码中,您可以看到我已经尝试过Object.defineProperty以及手动将函数添加到目标。但在测试中:
var product = new Product();
product.setProductID("123456789");
product.setProductName("Generic Shoes");
product.setUrlTitle("http://some/brand/get");
console.log("Product: ", product.getProductName(), product.getProductID(), product.getUrlTitle());
它会产生错误的结果:
Product: http://some/brand/get http://some/brand/get http://some/brand/get
而不是预期的
Product: Generic Shoes 123456789 http://some/brand/get
这肯定是因为我正在覆盖每个作业的定义。有没有更好的方法来解决这个问题,而不必为每个属性包含一个get / set方法,同时仍然保持getPropertyName()和setPropertyName(value)的正确函数命名约定?
答案 0 :(得分:3)
如果您选中window._val
,则会在运行代码后看到它等于http://some/brand/get
。因此,所有函数都是从同一个变量读取和写入,因为var _val
时new Function("...");
的范围会丢失。
您应该只在对象的原型上定义函数 - target
:
function generateGetterAndSetter(target: Object, key: string) {
var getMethodName = 'get' + key.charAt(0).toUpperCase() + key.slice(1);
var setMethodName = 'set' + key.charAt(0).toUpperCase() + key.slice(1);
target[getMethodName] = function() {
return this[key];
};
target[setMethodName] = function(val) {
this[key] = val;
};
}
答案 1 :(得分:1)
我不知道ts。但是自从ES2015(又名&#34; ES6&#34;)规范以来,JavaScript现在具有proxies。代理允许您创建对象(外观)其他对象的真实代理。
var obj = new Proxy({}, {
get: function(target, name) {
if (!(name in target)) {
console.log("Getting non-existant property '" + name + "'");
return undefined;
}
return target[name];
},
set: function(target, name, value) {
if (!(name in target)) {
console.log("Setting non-existant property '" + name + "', initial value: " + value);
}
target[name] = value;
return true;
}
});
console.log("[before] obj.foo = " + obj.foo);
obj.foo = "bar";
console.log("[after] obj.foo = " + obj.foo);