How do I restore an object's prototype after r

2020-02-07 05:59发布

问题:

I have a typescript class with a getTotal() method on the prototype.

class Score {
    roundOne: any;
    roundTwo: any;
    roundThree: any;
    roundFour: any;
    roundFive: any;
    roundSix: any;
    roundSeven: any;
    getTotal() {
      let total = 0;
      if(!isNaN(parseInt(this.roundOne))) total+=parseInt(this.roundOne);
      if(!isNaN(parseInt(this.roundTwo))) total+=parseInt(this.roundTwo);
      if(!isNaN(parseInt(this.roundThree))) total+=parseInt(this.roundThree);
      if(!isNaN(parseInt(this.roundFour))) total+=parseInt(this.roundFour);
      if(!isNaN(parseInt(this.roundFive))) total+=parseInt(this.roundFive);
      if(!isNaN(parseInt(this.roundSix))) total+=parseInt(this.roundSix);
      if(!isNaN(parseInt(this.roundSeven))) total+=parseInt(this.roundSeven);

      return total;
    }
}

The method works for my needs until I save an instance of 'Score' to localStorage and try to retrieve it. The prototype is stripped from the object so I no longer have access to the getTotal() method. Aside from restructuring my code, is there any way to reattach or point the objects to their prototype when I retrieve them from localStorage? Something along the lines of:

let scores = JSON.parse(localStorage.getItem('scores'));

scores.forEach(function(score){
  // reattach or point to prototype here
})

回答1:

Parsing a json doesn't result in instance of classes but with simple js objects which contain the same properties.

You have (at least) two ways to solve this:
(1) Add a constructor which can handle this state object:

class Score {
    roundOne: any;
    roundTwo: any;
    ...

    constructor(state: Score) {
        this.roundOne = state.roundOne;
        this.roundTwo = state.roundTwo;
        ...
    }

    getTotal() {
        ...
    }
}

let scores = (JSON.parse(localStorage.getItem('scores')) as Score[])
    .map(score => new Score(score));

Notice that even though I use the type Score for the state objects it's not really the case, they just share the same structure (minus the method). You can make an interface for that as well:

interface State {
    roundOne: any;
    roundTwo: any;
    ...
}

(2) Use Object.assign:

let scores = (JSON.parse(localStorage.getItem('scores')) as Score[])
    .map(score => Object.assign(new Score(), score));