JavaScriptにおけるコンテキストの喪失

関数内に関数がある場合を考えましょう。 外側の関数をparent、内側の関数をchildと呼ぶことにします:

javascriptfunction parent() {
  function child() {
    
  }
}

前回のレッスンから、外側の関数で変数を定義すると、内側の関数からその変数にアクセスできることをご存知でしょう:

javascriptfunction parent() {
  let str = 'abcde';
  
  function child() {
    console.log(str); // 'abcde' を出力
  }
  child(); // 内側の関数を呼び出す
}

parent(); // 外側の関数を呼び出す

しかし、注意点があります:内側の関数は外側の関数のすべての変数にはアクセスできますが、thisにはアクセスできません。つまり、外側の関数が何らかのDOM要素にバインドされている場合、その中のthisはその要素を指しますが、内側の関数のthisは指しません!

では、内側の関数のthisは何を指すのでしょうか?答え:それはundefinedになります(厳格モードでは)。なぜなら、関数は何にもバインドされていないからです。

実際に確認してみましょう。ここにinput要素があるとします:

html<input id="elem" value="text">

このinput要素に、フォーカスが外れたときに呼び出される関数parentをバインドしましょう:

javascript"use strict";

let elem = document.querySelector('#elem');
elem.addEventListener('blur', parent);

// フォーカスが外れたときに呼び出される:
function parent() {
  // ここに何らかのコード
  
  function child() {
    // ここに何らかのコード
  }
  child(); // 子関数を呼び出す
}

二箇所でthisの内容をコンソールに出力してみましょう:parent関数内とchild関数内です:

javascript"use strict";

let elem = document.querySelector('#elem');
elem.addEventListener('blur', parent);

function parent() {
  console.log(this); // input要素への参照を出力
  
  function child() {
    console.log(this); // undefined を出力
  }
  child();
}

このコードを実行し、input要素のフォーカスを外してコンソールを確認してください。最初のconsole.logはinput要素への参照を出力し、二つ目は単にundefinedを出力することがわかります。このように、thisが予期せず必要なものを指さない状況を、コンテキストの喪失と呼びます。

Задание 1

ここで、両方の関数でinputのvalueを出力するように変更します。コメントで示された行で何が出力されるか確認してください:

javascript"use strict";

let elem = document.querySelector('#elem');
elem.addEventListener('blur', parent);

function parent() {
  console.log(this.value); // 何が出力される?
  
  function child() {
    console.log(this.value); // 何が出力される?
  }
  child();
}