TypeScript 1.8
我试图围绕如何使用set
访问器来拦截对象属性(和子属性)的编辑操作。它没有按照我的预期工作,我不知道我的代码是否有问题。限制ot Typescript设置访问器或问题与我的代码?
这里是我的类的摘录:
private setAction:number = 0; //track # of edits
private _person:{ //data to be edited
name:string,
data:{
activities:Array<{
activityName:string,
funFactor:number
}>,
country:string
}
};
//public interfaces for set/get operations
public set person(val:any){
//indicate which edit is occuring
console.log('setting _person: setAction='+this.setAction);
if(!this._person) this._person = val;//initial set operation
let p = this._person;
p.name = val.name || p.name;
p.data.activities = val.data.activities || p.data.activities;
p.data.country = val.data.country || p.data.country;
}
public get person(){
return this._person;
}
public addActivity(name:string,value:number){
this.person.data.activities.push(
{activityName:name,funFactor:value});
}
//Edit this.person and test whether Set Accessor is called
onLoad(){
console.log('Incrementing setAction to '+ ++this.setAction);
this.person = {
name:'Mary',
data:{
activities:[],
country:'Argentina'
}
};
console.log('Incrementing setAction to '+ ++this.setAction);
this.person.name = 'Janet';
console.log('Incrementing setAction to '+ ++this.setAction);
this.addActivity('Bowling',7);
console.log('Incrementing setAction to '+ ++this.setAction);
this.person.data.country = 'Mexico';
console.log('Incrementing setAction to '+ ++this.setAction);
this.person.data.activities[0].funFactor = 8;
console.log(this.person);
}
当onLoad
被调用时,下面是输出到控制台:
递增的setAction 1
设置_person:setAction命令= 1
递增setAction为2
递增的setAction至3
递增的setAction至4
递增的setAction至5
对象{名: “珍”,数据:对象}
的data
在最终Object
更新为country="Mexico"
和Bowling funFactor=8
。所以所有编辑都成功完成,但Set
访问器只被调用一次。为什么是这样?
看看the docs(向下滚动到访问器部分)没有提到这个限制。
其他注意事项: 据我所知,为了执行person.name='Janet'
,我需要先得到person
,所以我希望get
要对所有这些操作调用。但由于person.name
从'玛丽'改为'珍妮特',确实设为为一个新值。那么,为什么不是二传手?我正在努力处理它的逻辑。我期望这个过程是:1)get person
,2)set person.name
。
当属性从一个值更改为另一个值时,不应该调用getter和setter吗?
回答
我一直以为get
和set
进行时性能读取或写入调用。这就是它向我解释的。 TypeScript文档说'TypeScript支持getters/setter作为拦截对象'成员的访问方式'。 RadimKöhler帮助我理解,当代码不与对象属性交互时,而是与对象引用交互时,将调用这些函数。总之,当我执行person.name='Janet'
时,虽然属性值发生变化,但person
仍然是指内存中的同一个对象,所以没有set
操作。
我明白,为了执行'person.name ='Janet'',我需要先得到'person',所以我希望'GET'是正如你所提到的那样呼吁所有这些行动。然而,由于'person.name'从'Mary'变成了'Janet',它确实**将**设置为一个新值。那么,为什么不是二传手?我正在努力处理它的逻辑。我期望的过程是:1)'get person',2)'set person.name' – BeetleJuice
那么1)得到人..意味着给我参考人。因此,当我们改变名称时,我们在内存中有一个地址(这是参考),其中人员实例是2)。我们不会改变对人的引用。它仍然是同一个对象..只是某处(在堆上)改变了它的设置名称。因此,这个人的二传手是真实的,以引用这个人。不涉及与该实例相关的属性。也许试着准备一些关于引用和值类型的东西。 http://www.zsoltnagy.eu/understand-value-and-reference-types-in-javascript/ –
我对引用类型和值类型之间的区别有所了解(感谢您的链接;我会看一看) 。我不知道“* setter是真的引用,而不是属性*”这是有道理的,但我链接到的Typescript文档没有提及它。你有没有参考这个,你可以添加到你的答案? – BeetleJuice