Arm*_*bie 1 javascript properties decorator typescript
我编写了一个带有属性装饰器的类,它在设置了装饰属性时在类中设置了一个标志.我还希望能够从该类的一个实例复制到另一个实例.问题是当我在一个对象上设置属性值时,另一个对象上的属性值也会发生变化,就好像该属性是静态的一样.我是JavaScript和TypeScript的新手.我错过了什么?
运行下面的文本代码将记录:
Setting propNum from undefined to 0
testclass.ts:18 Setting propNum from 0 to 123
test.spec.ts:13 t1.propNum = 123
test.spec.ts:14 t2.propNum = 123
Run Code Online (Sandbox Code Playgroud)
t1.propNum应该仍为零
//
// property decorator to set dirty flag automatically for any decorated property
//
function testProperty( target: any, key: string ) {
// property value
var _val = this[key];
// property getter
function getter() {
return _val;
};
// property setter
function setter( newVal ) {
if ( _val != newVal ) {
console.log( `Setting ${key} from ${_val} to ${newVal}` );
_val = newVal;
this._dirty = true;
}
};
//
// Delete original property and define new property with getter & setter
//
if ( delete this[key] ) {
// Create new property with getter and setter
Object.defineProperty( target, key, {
get: getter,
set: setter,
enumerable: true,
configurable: true
});
}
}
Run Code Online (Sandbox Code Playgroud)
export class TestClass {
private _dirty: boolean;
@testProperty
public propNum: number = 0;
constructor() {
this._dirty = false;
}
public copyFrom( tc: TestClass ) {
this.propNum = tc.propNum;
}
}
Run Code Online (Sandbox Code Playgroud)
describe( 'Copy Class Test', () => {
it( 'Copy Test', () => {
var t1 = new TestClass();
var t2 = new TestClass();
t2.propNum = 123;
console.log( `t1.propNum = ${t1.propNum}` );
console.log( `t2.propNum = ${t2.propNum}` );
expect( t1.propNum ).toBe( 0 );
t1.copyFrom( t2 );
expect( t1.propNum ).toBe( 123 );
});
});
Run Code Online (Sandbox Code Playgroud)
这里的主要问题是getter和setter共享相同的变量,而不是基于实例获取值.
它与执行此操作基本相同:
function TestClass() {
}
var value;
Object.defineProperty(TestClass.prototype, "propNum", {
get: function() { return value; },
set: function(val) { value = val },
enumerable: true,
configurable: true
});
Run Code Online (Sandbox Code Playgroud)
导致这种情况发生的原因:
var a = new TestClass(), b = new TestClass();
a.propNum = 2;
a.propNum === b.propNum; // true, because they're both referencing the same variable
Run Code Online (Sandbox Code Playgroud)
第二个问题是this[key]引用全局对象上的属性.
您可能想要做的是沿着这些方向(未经测试的代码):
function testProperty( target: Object, key: string ) {
const privateKey = "_" + key;
function getter() {
return this[privateKey];
}
function setter( newVal: any ) {
if ( this[privateKey] != newVal ) {
console.log( `Setting ${key} from ${this[privateKey]} to ${newVal}` );
this[privateKey] = newVal;
this._dirty = true;
}
}
Object.defineProperty( target, key, {
get: getter,
set: setter,
enumerable: true,
configurable: true
});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1658 次 |
| 最近记录: |