Javascript:setTimeoutの中のfunctionのthis

(まだ理解が浅いので間違っているかもしれない)

setTimeoutで実行するfunctionは別コンテキストで実行されるゆえに、(ブラウザで実行した場合は)thisがWindowになる:

const mountains = {
  names: ['fuji', 'tsurugi', 'ontake'],
  print: function() {
    setTimeout( function() {
      console.log(this); // Window
      console.log(this.names); // undefined
    }, 1000);
  }
}

ではどうやってmountains.namesを参照するか?アロー関数を使う:

const mountains = {
  names: ['fuji', 'tsurugi', 'ontake'],
  print: function() {
    setTimeout( () => {
      console.log(this); // mountainsオブジェクト
      console.log(this.names); // ['fuji', 'tsurugi', 'ontake']
    }, 1000);
  }
}

なぜか?アロー関数のthisはランタイム時ではなく定義されたときのスコープ(レキシカルスコープ)を引きずるため。 上記コードでは定義されたときのスコープはprint: function () の中であり、print: functionのスコープは mountainsオブジェクト。

なお、上記コードでfunctionをすべてアローに変更すると動かない:

const mountains = {
  names: ['fuji', 'tsurugi', 'ontake'],
  print: () => {
    setTimeout( () => {
      console.log(this); // mountainsオブジェクト
      console.log(this.names); // ['fuji', 'tsurugi', 'ontake']
    }, 1000);
  }
}

print: () のスコープはmountainsではなくその外側、つまり Windowだからである