키워드, 블록 스코프 -ECMAScript
글로벌 변수 오해
글로벌 오브젝트에 작성한 변수는 글로벌 오브젝트가 스코프입니다.
글로벌 오브젝트에 작성하여 글로벌 변수라고 부르는 것이지,
글로벌 오브젝트에서 보면 로컬 변수입니다.
var 키워드를 작성하지 않으면 글로벌 변수로 간주한다는 점으로 인해var키워드를 작성하지 않을 뿐이지 글로벌 변수는 var 키워드를 사용하지 않는다는것이 아닙니다.
글로벌 변수도 var 키워드를 사용하여
var global = “”;
형식으로 작성하는 것이 정확한 작성법입니다.
글로벌 변수는 객체지향 관점에서 보면 단점이라고 할 수 있습니다.function 안에서 글로벌 오브젝트에 작성된 글로벌 변수를 사용할 수는 있지만,
다른 프로그램에서 글로벌 변수 값을 변경 하거나 재사용 할 수도 있는 위험이 있습니다.
이러한 경우는 자칫 오류를 만들게 되어 객체 지향 기본에서 어긋나는 행동입니다.
let 키워드
let 키워드 변수 선언 형태
let sports = “축구”;
let 키워드는 var 키워드의 문제점을 해결하기 위한 것으로
다음과 같은 특징이 있습니다.
- 함수 안에 작성한
let변수는 함수가 스코프 입니다. - 함수 안에
if(a=b){let sports = “축구”}형태의 코드를 작성했을 때,sports변수는 함수가 스코프가 아니라if문의 블록{}이 스코프입니다. - 블록{} 밖에 같은 이름의 변수가 있어도 스코프가 다르므로 변수 각각에 값을 설정할 수 있고 그 변수 값이 유지됩니다.
- 블록{} 안에 블록{}을 계층적으로 작성하면 각각의 블록이 스코프입니다.
- 같은 스코프 안에서 같은 이름의
let변수는 허용되지 않습니다.
블록 스코프
let 변수를 선언하는 가장 큰 목적은 스코프이며 그중에서도 블록 스코프가 돋보입니다.
블록{} 안과 밖에 변수 이름이 같더라도 스코프가 다르므로 변수가 선언되고 각 변수에 할당된 값이 대체되지 않고 유지됩니다.
1 | let sports = "축구"; |
if문 앞에 같은 이름의sports변수가 있지만 블록{}을 기준으로
스코프가 다르므로 각sports변수에 값이 할당되어“축구”가“농구”로 대체되지 않고 각 값이 유지됩니다.
let과 this 키워드
1 | 1. var music = "음악"; //var (this) |
var키워드는 현재 글로벌 오브젝트의 상태이고this는 글로벌 오브젝트를 참조하게 되어music변수 값인 “음악”이 출력됩니다.
let키워드로 선언,할당한 후this로sports값을 출력하면undefined가 출력됩니다.this가 글로벌 오브젝트를 의미하여window오브젝트를 참조하는데window오브젝트에let변수가 없다는 것은window오브젝트에let변수가 설정되지 않는다는 의미 입니다.
이점이var변수와let변수의 차이입니다.
function
function도 스코프를 가지므로 하나의 블록 스코프입니다.function 안에 선언된 모든 변수가 function내의 스코프에 속하고function안에 if 블록{}은 스코프 안에 스코프를 가지는 계층 구조의 형성입니다.
1 | let sports = "축구", music = "재즈"; |
var변수와 마찬가지로 함수안에서music변수를 검색하고,없으면
함수 밖으로 나가 검색합니다. 함수안에music변수가 있으므로
“클래식”이 출력됩니다.
- 함수안에
sports변수가 없으므로 함수 밖의sports값인 “축구”를 출력합니다.
이와 같이 let 변수도 가장 가까운 스코프에 있는 변수를 먼저 사용합니다.
1 | var sports = "축구"; // var sports |
strict모드에서window.get과 같이get()앞의 오브젝트 위치에window를 작성하면function get()내의this가window오브젝트를 참조합니다.함수 안에
sport변수가 있으므로 그 값인 “농구”를 출력합니다.window.get()형태로 호출했으므로this가window오브젝트를 참조하여get()함수 밖의var변수sports의 값 “축구”를 출력합니다.undefinedthis가window오브젝트를 참조하여get()함수 밖의music변수를 찾지만music변수가let으로 선언되어 있어this(window 오브젝트)로 참조할 수 없어undefined가 출력됩니다.
get()과 같이 오브젝트를 지정하지 않고 호출하면 this가 window 오브젝트를 참조하지 않습니다.
sports는var변수입니다.var변수는window오브젝트 지정과 관계없이 함수 안의 변수를 참조하여
“농구”가 출력됩니다.,3. 에러
window오브젝트를 작성하지 않고 호출하여this가window오브젝트를 참조하지못하고 엔진은 참조할 오브젝트 위치에undefined를 설정합니다.this는 참조할 오브젝트 위치에 있는undefined를 참조하게 되고TypeError가 발생합니다.
try-catch
try-catch문에서 try 블록{}기준으로 블록 스코프를 갖습니다.catch 블록은 스코프를 가지지 않으며 try 블록 스코프에 속합니다.
1 | let sports = "축구"; //try문 밖의 let sports |
try문블록{}스코프의sports값 출력 “농구”try문 밖의sports값 출력 “축구”
switch-case
switch-case 문에서 switch 블록이 블록 스코프입니다.switch 안에 case는 별도의 스코프를 갖지 않으며 switch 스코프에 속합니다.
1 | var count = 1; // switch문의 case1:을 실행하기 위해 count에 1할당 |
for()
for()문에서 var변수로 작성하는 것과 let변수로 작성하는 것에는 큰 차이가 있습니다.
let 변수는 반복할 때 마다 스코프를 갖는 반면, var 변수는 스코프를 갖지 않습니다.
1 | <ul> |
1 | var nodes = document.querySelector("ul"); |
querySelector(“ul”)으로 html에 작성된 li 요소 3개를 nodes 변수에 할당합니다.nodes.childern.length는 NodeList의 요소 수로 3입니다.for문을 반복하면서 각 li 요소마다 onclick 이벤트를 설정합니다.
클릭시 배경색을 변경하고 for문의 K 변수 값을 출력합니다.
어떤 li요소를 클릭하더라도 콘솔에 K값 3이 출력되며 3이 K의 최종값 입니다.
클릭한 li 요소에 해당하는 K변수 값을 출력하고 싶다면let변수를 사용하면 됩니다.
let
1 | var nodes = document.querySelector("ul"); |
li요소를 클릭하면 onclick이벤트를 설정했을 때 사용한 K변수 값을 출력합니다. 0,1,2
이는 let변수가 스코프를 갖기 때문입니다.
const
const 변수에 할당된 값은 상수가 됩니다.
상수는 재할당 할 수 없으며 재선언 할 수도 없습니다.
const 변수는 선언-초기화-할당을 한번에 합니다.
즉, const a;처럼 선언만 해놓을 수 없습니다. 반드시 const a = 0; 처럼 초기값을 할당해 줘야 합니다.
상수 선언에는 대소문자 모두 사용할 수 있지만, 일반적인 관습은 모두 대문자를 사용하는 것입니다.