(まだ理解が浅いので間違っているかもしれない)
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だからである