限制ot Typescript设置访问器或我的代码问题?

时间:2016-06-22 10:00:04

标签: typescript accessor

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?

回答

我一直认为在读取或写入属性时会调用getset。这就是它向我解释的方式。 TypeScript文档说' TypeScript支持getter / setters作为拦截对象成员访问的方式'。 RadimKöhler帮助我理解,当代码不与对象属性交互但使用对象引用时,会调用这些函数。简而言之,当我执行person.name='Janet'时,虽然属性值发生了变化,但person仍然引用了内存中的同一个对象,因此没有set操作。

1 个答案:

答案 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