- JavaScript의 Scope의 의미와 적용 범위를 이해할 수 있다
- JavaScript의 Scope 주요 규칙을 이해할 수 있다
- 중첩 규칙
- block level vs. function level
- let, const, var의 차이
- 전역 변수와 전역 객체의 의미
범위, 영역을 뜻하는 말로 변수 접근 규칙에 따른 유효 범위를 말한다. 변수는 어떠한 환경 내에서만 사용이 가능하며, 프로그래밍 언어는 각각의 변수 접근 규칙을 갖고 있다. 자바스크립트는 기본적으로 함수가 선언되는 동시에(lexical) 자신만의 Scope를 갖는다. 우리는 이 범위라는 개념을 이용해서 한줄의 코드를 작성할때 어디까지가 잘 되는 코드이고 어디까지가 잘 작동되지 않는 코드인지 파악할 수 있다. 조금 더 쉽게 말해서, 앞에서는 변수를 만들고 값을 할당하면 어디서든 그 변수 이름으로 할당된 값을 가져올 수 있었다. 그런데 사실 변수에는 유효한 범위가 있어서 그 범위를 벗어나면 오류가 발생하게 된다. 변수의 유효범위에 대해서 살펴보자.
let x = 3;
console.log(x); // 3
이 경우 잘 실행된다. 이번에는 같은 내용을 함수 안에 넣어주겠다.
function myFunction(){
let x = 3;
console.log(x);
}
myFunction(); // 3
이 함수도 잘 실행된다. 그렇다면 함수 밖에서 변수를 출력하게 되면 어떻게 될까?
1 function myFunction(){ //블록문(block statement)
2 let x = 3; // 로컬 변수, 지역 변수(Local Variable)
3 console.log(x);
4 }
5
6 myFunction(); // 3
7 console.log(x); // ReferenceError: x is not defined
어떻게 된 일일까?
자바스크립트에서는 중괄호'{}'로 감싼 코드를 블록문(Block Statement)라고 부른다. 그리고 그 블록문 안에 선언된 변수를 로컬 변수 혹은 지역 변수(Local variable)라고 부른다. 로컬변수는 블록문 내에서만 사용할 수 있는 변수이다. 변수 x의 scope 즉, 변수x가 유효한 범위는 myFunction안에서 만이다.
7번줄에서 사용한 x는 변수x가 유효한 범위 내에 있지 않기 때문에 정의되지 않았다는 오류가 발생한다.
이번에는 변수x를 함수 밖으로 꺼내보자.
1 let x = 3; // 글로벌 변수, 전역 변수(Global Variable)
2 function myFunction(){
3 console.log(x);
4 }
5
6 myFunction(); // 3
7 console.log(x); // 3
이 경우 7번줄도 3을 출력함을 확인할 수 있다. 3번줄의 변수x는 1번줄에서 선언한 변수x이다. 로컬 변수와 반대로 블록문 밖에서 선언한 변수는 블록문 안에서도 사용할 수 있는데 이런 변수를 글로벌 변수 혹은 전역 변수라고 부른다. 글로벌 변수는 이름에서도 알수 있듯이 코드를 작성할 수 있는 파일 어디서나 사용할 수 있다.
그런데 만약 myFunction안에서 똑같은 이름의 변수를 다시 선언하면 어떻게 될까?
1 let x = 3; // 글로벌 변수, 전역 변수(global variable)
2 function myFunction(){
3 let x = 5; //로컬 변수, 지역 변수(local variable)
4 console.log(x);
5 } // 2 - 5번까지 local scope
6
7 myFunction(); // 5
8 console.log(x); // 3
함수의 실행 순서를 확인해보면, 1번줄부터 변수x가 선언되고 2번부터 죽 내려오다가 7번줄에서 함수 myFunction을 호출한다. 그럼 2번줄로 올라가서 myFunction함수를 실행하게 되고 3번줄에서 로컬 변수 x를 선언하게 된다. 자연스럽게 4번줄에서 사용한 변수x는 3번줄의 로컬 변수x를 사용하게 되는 것이므로 할당값인 5를 콘솔에서 출력하게 된다. 즉, 블록문 내부에서 선언된 지역 변수가 있는지를 먼저 확인하고 있으면 그 지역 변수를 사용하고 없을 경우 전역 변수를 사용한다. 5를 출력하고 함수는 종료되고 마지막 8번줄의 변수x는 블록문 밖에 있으므로 로컬 변수의 영역에서 벗어나있다. 그렇기 때문에 자연스럽게 1번 줄에서 선언한 글로벌 변수x가 사용되면서 콘솔에 3이 출력된다.
다음 코드를 실행했을 때 출력되는 내용은?
1 function myFunction() {
2 let x = "해리포터";
3 x = "호그와트";
4 }
5
6 myFunction();
7 console.log(x);
함수 정의 후 6번줄에서 myFunction을 호출하는데 2번줄에서 문자열 "해리포터"가 로컬 변수x에 할당되고, 바로 3번줄에서 문자열 "호그와트"가 로컬 변수x에 할당된다. 그리고 함수는 끝나서 다시 함수를 호출한 6번줄로 돌아가는데, 더 이상 동작할 부분이 없으니 7번줄로 넘어간다. 7번 줄에서 x를 출력하려고 하는데, 앞서 정의한 x들은 로컬 변수이므로 함수 밖에서 언제든 접근 가능한 글로벌 변수x는 당연히 존재하지 않는다. 따라서 이 프로그램을 실행하면 오류가 발생한다.
다음 코드를 실행했을 때 출력되는 내용은?
1 let x = 100;
2
3 function myFunction() {
4 let y = 40;
5 console.log(x + y);
6 }
7
8 myFunction();
9 console.log(x);
8번줄에서 myFunction을 호출한다. 3번줄로 올라가서 함수가 실행되고 지역 변수y에 40을 할당하고 5번 줄에서는 console.log(x + y)를 한다. 그런데 로컬 변수x는 존재하지 않기 때문에 글로벌 변수x에 담긴 100을 가져온다. 그리고 로컬 변수y는 존재하기 때문에 로컬 변수y에 담긴 40을 사용한다. 따라서 140을 출력한다.
이후 함수는 종료되고 9번줄의 console.log(x)를 하는데, 이때는 글로벌 변수x를 사용하기 때문에 100이 출력된다. 결론적으로 콘솔에 출력된 것을 보면 아래와 같다.
140
100
// let의 경우
// 사례1
for(let i = 0; i<5; i++){
console.log(i);
}
/*
0
1
2
3
4 */
console.log('final i:', i);
// ReferenceError! 'i is not difined'
// Block 범위를 벗어나는 즉시 변수 사용 불가능
//사례2
let b = 10; //b는 10 선언
if(true){
let b = 20;
console.log(b);// 20
}
console.log(b); //10
// var의 경우
// 사례1
for(var i = 0; i<5; i++){
console.log(i);
}
/*
0
1
2
3
4 */
console.log('final i:', i); // 'final i: 5'
// block 범위를 벗어나도 같은 function scope에서는 사용 가능
// 사례2
var a = 10;
if(true){
var a = 20; // a = 10 선언했지만 if 안에서 재선언 가능
console.log(a); // 20 (위의 재선언 영향)
}
console.log(a); // 20 (함수 안의 변수가 밖에도 영향을 미침
값이 변하지 않는 변수 즉 상수(constant)를 정의할 때 사용한다. let과 동일하게 Block Scope를 따른다. 값을 재정의하려고 하면 TypeError가 난다.
const pi=3.14
pi = 3.1415 //uncaught TypeError
let | const | var | |
---|---|---|---|
유효 범위 | Block Scope | Block Scope | function Scope |
값 재정의 | 가능 | 불가능 | 가능 |
재선언 | 불가능 | 불가능 | 가능 |
전역 범위를 대표하는 객체 Window
Global Scope에서 선언된 함수, 그리고 var 키워드를 이용해 선언된 변수는 window 객체와 연결된다. 단, 전역 범위에 너무 많은 변수를 선언하지 않도록 주의하자!
var myName = 'Minion';
console.log(window.myName); //Minion
function foo(){
console.log('bar');
}
console.log(foo === window.foo); //true
절대로 선언 키워드(var, let, const)없이 변수를 초기화하지 말아라!
function showAge(){
//age는 선언을 하지 않고 할당만 함,
// 에러가 나지 않고 전역 변수로 취급된다 age === window.age
age = 90;
console.log(age);
}
showAge(); //90
console.log(age); //90
이런 실수를 방지하고 싶을 경우, 'Strict Mode'를 사용하자. 'use strict';를 미리 적용하고 코딩 작업을 하자. 콘솔창에서는 사용할 수 없고, 파일을 저장한 다음에 사용할 수 있다.
혼자 책보면서 독학하다가 지역변수, 전역변수가 이해가 안되서 찾다가 보게됬는데 정리가 너무 잘되어있어서 이해하는데 큰 도움이 됬네요! 잘보고가요 감사합니닷!!