JSのスコープについての現在の見解

JSのスコープについての現在の見解:


簡単な例でスコープを理解

scope.js
const x = 3; 
function f(){ 
   console.log(x); //3 
   console.log(y); // y is not defined (error) 
} 
f(); 
const y = 5; 
x : 関数を呼ぶ出す前に存在している →関数にも使える

y : 関数を呼び出した後に存在している → 定義前に呼び出された関数には使えない

スコープ : 変数を参照できる範囲


グローバルスコープ

グローバルスコープは全てのプログラム内で使用可能になる!!!

グローバルスコープで定義された変数をグローバル変数と呼ぶ!

しかし!

グローバル変数を濫用しすぎると、かなり困るから注意。。。

let name = "makoto"; 
let age = 19; 
 
function greet(){ 
   console.log(`こんにちは、${name}`); //makoto 
} 
 
function ageVerification(){ 
   console.log(`私の年齢は、${age}です`); //19 
} 
トップにlet name / let ageを定義することで、それ以下に記述している関数に影響してくる(プログラム中のどこで定義された関数でもname/ageの値を変更できてしまう)

それは避けたいので、オブジェクトを使用して改善していく

改善.js
let user = { 
   name : "makoto", 
   age : 19 
}; 
 
function greet(user){ 
   console.log(`こんにちは、${user.name}`) //makoto 
} 
 
function ageVerification(user){ 
   console.log(`私の年齢は、${user.age}です`); //19 
} 
 
greet(user); //makoto 
このように記述することで、よく使われるnameなどの識別子をなどもグローバル変数にせずに使用することができる。

グローバル変数:name/age → user


ブロックスコープ

{ //ブロックスコープ開始 
const x = 5; 
console.log(x); //5 
} //ブロックスコープ終了 
console.log(x); //x is not defined 
ブロックで囲むことで、ブロック内で定義した変数の値はブロック内でしか効力がない


クロージャー

独立した変数を参照する関数

let f; 
{ //ブロックスコープ 
   let o = {name : "makoto", age : 19}; 
   f = function(){ //スコープ内で関数を定義すると関数がスコープを保持する(スコープ内を参照する覗き窓) 
      console.log(o.name); //makoto 
      return o; 
   } 
}  //ブロックスコープ 
let oRef = f(); //oオブジェクトを参照する変数を定義 
console.log(oRef);{name:"makoto"} 
oRef.name = "keigo"; //関数(のぞき窓)越しにスコープ内の値を変更! 
console.log(oRef);{name:"keigo"} 
通常は外部からスコープにアクセスできないが、関数を定義することで覗き窓を作ることができる!


関数の巻き上げ

関数宣言.js
f(); // "呼び出せた!" 
function f(){ 
console.log("呼び出せた!") 
} 
関数宣言の場合、関数より先に関数の呼び出しを記述していても、関数の巻き上げで呼び出すことができる!

変数に代入された関数式.js
f(); // f is not defined 
let f = function(){ 
console.log("呼び出せた!") 
} 
変数に代入すると、巻き上げは効かなくなる


TDZ(temporal dead zone)

var.js
console.log(x); //undefind 
var x = 5; 
console.log(x); //5 
let.js
console.log(x); //x is not defined 
let x = 5; 
console.log(x); // 
つまりvarは宣言した瞬間にプログラム全体で存在していることになる

なので、undefinedと表示された

let は、定義されたそれ以降から存在することになるのでこのような結果になる。(letで宣言された変数は宣言されるまで存在しない)

コメント