TypeScript 1.8
我试图围绕如何使用set
访问器拦截对象属性(和子属性)的编辑操作。它不像我预期的那样工作,我想知道我的代码是否有问题。
以下是我班级的摘录:
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
Object {name:“Janet”,data:Object}
最终data
中的Object
已更新为country="Mexico"
和Bowling funFactor=8
。因此,所有编辑都已成功完成,但Set
访问者仅被调用一次。为什么是这样?
查看the docs(向下滚动到访问者部分)并未提及此限制。
附加说明:
我了解为了执行person.name='Janet'
,我需要首先获得person
,因此我希望在所有这些操作上调用get
。但是,由于person.name
已从“Mary”更改为“Janet”,因此确实设置为新值。那么为什么不召唤二传手呢?我正在努力解决它的逻辑问题。我希望这个过程是:1)get person
,2)set person.name
。
当属性从一个值更改为另一个值时,是否应该调用getter和setter?
回答
我一直认为在读取或写入属性时会调用get
和set
。这就是它向我解释的方式。 TypeScript文档说' TypeScript支持getter / setters作为拦截对象成员访问的方式'。 RadimKöhler帮助我理解,当代码不与对象属性交互但使用对象引用时,会调用这些函数。简而言之,当我执行person.name='Janet'
时,虽然属性值发生了变化,但person
仍然引用了内存中的同一个对象,因此没有set
操作。
答案 0 :(得分:1)
嗯,setter
在该行
this.person = {
name:'Mary',
data:{
activities:[],
country:'Argentina'
}
};
其他人实际上是在呼叫 getter
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;
因为this.person.data
就像
let person = this.person; // getter
person.data = ...
EXTEND
有a working example显示问题在起作用。当我们调用引用属性的setter(例如Person)时,我们分配一个引用。稍后,当我们更改引用对象的属性时,我们不会更改原始引用。在这里查看:
class Person {
// name has setter
private _name = null;
set name(name: string) { this._name = name; console.log(name) };
get name() { return this._name}
// age does not one
age: number = null;
}
class PersonHolder {
private _person;
set person(person: Person) { this._person = person;
console.log(JSON.stringify(person)) };
get person() { return this._person}
}
var holder = new PersonHolder();
// this will log to console { name: null, age: null}
holder.person = new Person();
// this will log to console "new name"
holder.person.name = "new name"
// this will NOT log to console... no setter
holder.person.age = 11;
直播example