0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【javascript】変数の巻き上げ

Last updated at Posted at 2020-06-17

こちらの記事は以下の書籍を参考に執筆しました

##letによる変数の巻き上げ
巻き上げとは、変数が宣言されたスコープの内側では、変数がスコープ全体(letならブロック全体,varなら関数全体)を消費する振る舞いのこと。

...そう言われてもよくわからない。
まずは例を見てみる。

if (condition) {
  //----- myDataのスコープはここから -----
  doSomePrework();
  /*その他のコード*/
  let myData = getData();
  /*その他のコード*/
  doSomePostwork();
  //----- ここまで -----
}

出典:入門JavaScriptプログラミング

上記の例ではmyData変数はif文のブロックスコープ内にあり、
まだ宣言されていなくてもアクセスできる。
//----- myDataのスコープはここから ----- //----- ここまで -----の間のどこにmyDataを宣言してもどこからでもアクセスできるということ。

次の例は少々難しい。

//----- 外側のmyDataのスコープはここから -----
let myData = getDefaultData();

if (condition) {
  //----- myDataのスコープはここから -----
  doSomePrework(myData);
  /*その他のコード*/
  let myData = getData();
  /*その他のコード*/
  doSomePostwork();
}
//----- ドト側のmyDataのスコープはここまで -----

出典:入門JavaScriptプログラミング

上記の場合myData2つ存在する。
ややこしいのはdoSomePrework関数が呼び出された時点で引数のmyDataは外側のmyDataであるというのは間違であるということだ。
つまり、
内部のmyDataはスコープ全体(ifブロック全体)を消費しているため、doSomePrework関数に入るのはこの内側のmyDataだ。
このように宣言される前でも変数を巻き上げて使用できてしまうのが変数巻き上げである。

#letで巻き上げられる変数へ宣言前にアクセスすると?
letは変数をブロックの先頭へ巻き上げ、varは関数の先頭へ巻き上げる。
letで宣言された変数が宣言される前にスコープ内でアクセスされた場合、参照エラー(ReferenceError)となる。
varではスコープ内であれば宣言される前であってもアクセスできるが、値は常に未定義となる。

console.log(foo) //参照エラー
let foo=2;

出典:入門JavaScriptプログラミング

以下のコードの結果はどうなるだろうか

let num = 0;

function getNum() {
  if (!num) {
    let num = 1;
  }
  return num;
}

console.log(getNum());  //結果は??

出典:入門JavaScriptプログラミング

答えは1ではない。

解説すると、

let num = 0;

function getNum() {
  if (!num) {
    //----- 内部のnumスコープはここから -----
    let num = 1;
    //----- 内部のnumスコープはここまで -----
  }
  return num;  //新しい let 変数はスコープを外れたため、この変数は0のまま 
}

console.log(getNum());

出典:入門JavaScriptプログラミング

つまり、はif文内で宣言されたnumそのスコープ内でしか有効でないためgetNum関数のreturnされるnumは外側のものであるということだ。

これを解決するにはnumに1を代入する時にletを取ればいい。

let num = 0;

function getNum() {
  if (!num) {
    //letをとる。
    num = 1;
  }
  return num;
}

console.log(getNum());  //1

出典:入門JavaScriptプログラミング

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?