Javascript destructuring question

So I was playing around with destructuring in repel and when I destructure a function with the “this” keyword in my object code below I was gotten back, NaN. Does destructuring causes this keyword to lose its reference?

const scoreTracker = {
    score:0,
    incrementScore(){
      return this.score+=1;
    },
    resetScore(){
      return this.score = 0;
    }
}


const {incrementScore} = scoreTracker;

console.log(incrementScore);
console.log(incrementScore());
1 Like

What a great question!

So, this definitely looses its reference in this case, but if you really want to, there are at least three ways to work around this, depending on your situation. These examples are based solely on Ori Drori`s and Ilshidur’s answers to a similar question over on StackOverflow, so I definitely encourage you to go read their full answers, with a different base example, and please give his answer a thumbs up while you’re there!

Anyway, here are the ways they suggest, as applied to your example. (I wish we could have live code snippets here in discourse :frowning: , oh well, you’ll just have to move them to your repl of choice.)

Approach 1: Auto-bind with a getter

const scoreTracker = {
    score: 0,
    _incrementScore(){
      return this.score += 1;
    },
    get incrementScore(){
      if(!this._incrementScore.name.startsWith('bound ')) {
        this._incrementScore = this._incrementScore.bind(this);
      }
      return this._incrementScore;
    },
    resetScore(){
      return this.score = 0;
    }
}

const { incrementScore } = scoreTracker;

console.log(incrementScore);
console.log(incrementScore());
console.log(incrementScore());
console.log(incrementScore());

Approach 2: Auto-bind with a Proxy

const handler = {
  get: function(target, prop, receiver) {
    // if method, and not bound, bind the method
    if (
        typeof target[prop] === 'function' 
        && !target[prop].name.startsWith('bound ')
      ) {
      target[prop] = target[prop].bind(target);
    }
    
    return target[prop];
  }
};

const scoreTracker = new Proxy({
    score:0,
    incrementScore(){
      return this.score += 1;
    },
    resetScore(){
      return this.score = 0;
    }
}, handler);

const {incrementScore} = scoreTracker;

console.log(incrementScore);
console.log(incrementScore());
console.log(incrementScore());
console.log(incrementScore());

Approach 3: Class binding

class ScoreTracker {
  // field declarations not currently supported, but at stage 3
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Field_declarations
  // score = 0; 
    
  constructor() {
    this.score = 0;
    this.incrementScore = this.incrementScore.bind(this);
  }
  
  incrementScore(){
    return this.score += 1;
  }

  resetScore(){
    return this.score = 0;
  }
}

const { incrementScore } = new ScoreTracker();

console.log(incrementScore);
console.log(incrementScore());
console.log(incrementScore());
console.log(incrementScore());
1 Like

Hey thanks for your reply ! it is interesting how the “this” reference is not lost in class binding ,i always have assumed objects instantiated from class based syntax and object literal should be the same type of objects. I will read more about it later and play around more , thanks again for your insight :slight_smile: .

1 Like