// "use strict" value = 100; function point() { value = 300; console.log("함수: ", value); }; point(); // 300
글로벌 변수는 글로벌 오브젝트의 로컬 변수입니다. var value = 100처럼 var 키워드 사용이 정상입니다.
그런데 여기서 var 키워드를 작성하지 않으면 글로벌 변수로 간주하는데 이것이 문제가 될 수 있습니다.
"use strict" function point() { try { value = 300; console.log("함수: ", value); } catch(e) { console.log("글로벌 변수 사용 불가"); } }; point(); // 300
let sports = "축구"; sports = "농구"; console.log(sports); // let sports = "배구"; --- syntax error { let sports = "탁구"; console.log(sports); }; // 농구 // 탁구
블록 기준으로 값이 정의되며 블록 안과 밖의 변수는 구분됩니다. 즉 같은 이름이지만 각각 다르게 존재할 수 있습니다.
블록 안과 밖의 스코프가 다르기에 변수 이름이 같아도 값이 대체되지 않습니다.
스코프에 같은 이름을 사용하는것을 불가능합니다.
let sports = "축구"; function show() { let sports = "농구" console.log("안:",sports); }; show(); console.log("밖:",sports); // 안: 농구 // 밖: 축구
let sports = "축구"; function show() { console.log(sports); }; show();
function 밖의 let 변수를 function 안에서 사용 가능합니다 (클로저)
let sports = "축구"; try { let sports = "농구"; console.log("안:", sports); abc = error; } catch(e) { console.log("catch: ", sports); }; console.log("밖: ",sports); // 안: 농구 // catch: 축구 // 밖: 축구
try-catch문도 블록 스코프 이며 try블록 { }기준으로 안과 밖에 같은 이름의 let변수 선언이 가능합니다.
catch()에서 try밖의 변수를 사용 가능합니다.
let item = 1; switch (item) { case 1: let sports; break; case 2: // let sports; // 주석 해제시 컴파일 에러 발생 default: console.log(sports); };
let sports = "축구"; if(sports) { let sports = "농구"; console.log("안:", sports); }; console.log("밖: ", sports); // 안: 농구 // 밖: 축구
let value1; let value2 = "테스트"; let value3 = "테스트2", value4; let value3 = "테스트2", value4 = "테스트3"; let value1 = (10 + 20);
Syntax
let name1 [= value1] [, name2 [= value2] ]
name1, name2에 변수 이름 작성
let book = "책"; let one = 1, two = (10 + 20); // let five = 5, let six = 6; // let five = 5, var six = 6;
for()문에서 반복할 때마다 var 변수는 스코프를 갖지 않는 반면, let 변수는 스코프를 가집니다.
<ul class="sports"> <li>축구</li> <li>농구</li> <li>야구</li> </ul> <input id="output" type="text" readonly>
var node = document.querySelector(".sports"); var $output = document.querySelector("#output"); for(var k = 0; k< node.children.length; k++) { node.children[k].onclick = function(event) { event.target.style.backgroundColor = "yellow"; $output.value = k; }; };
어떤 것을 클릭해도 3이 출력되는 것을 확인할 수 있습니다. 이는 var k = 0; 에서 k변수의 스코프는 함수 전체이기 때문에 세가지 li 요소들이 하나의 k변수를 가지게되고 for문이 끝날때 할당된 3을 출력하게 되는 것입니다.
<ul class="sports"> <li>축구</li> <li>농구</li> <li>야구</li> </ul> <input id="output" type="text" readonly>
var node = document.querySelector(".sports"); var $output = document.querySelector("#output"); for(let k = 0; k< node.children.length; k++) { node.children[k].onclick = function(event) { event.target.style.backgroundColor = "yellow"; $output.value = k; }; };
var k =0; 을 let k =0; 으로 바꾸었습니다. 이제 이벤트 발생시 그 때의 k값을 출력합니다. 이를 통해 k는 블록단위로 가져가며 구분되는것을 확인할 수 있습니다.
이는 장점만 있는것은 아닌데, 만일 반복문의 반복 횟수가 수천 수만번이 넘어가게 될 때 let변수로 설정하면 각각의 블록이 메모리를 차지하게도면서 퍼포먼스가 떨어질 수 있습니다.
var music = "음악"; let sports = "축구"; console.log(this.music, this.sports); // 음악 // undefined
"use strict" var globalVar = "글로벌"; let globalLet = "블록"; console.log(this.globalVar); console.log(this.globalLet); // 글로벌 // undefined
모든 js파일에서 글로벌 오브젝트에 작성한 var 변수와 let변수를 공유할 수 있습니다.
var globalVar = "var변수"; var globalLet = "let변수": console.log(globalVar); console.log(globalLet);
위처럼 두 개의 js파일을 사용하면서 first.js에서 선언한 변수들을 second.js에서 사용이 가능합니다.
그리고, 글로벌 오브젝트에 작성했지만 공유하고 싶지가 않을 경우 블록을 사용하면 글로벌 오브젝트의 지역 변수로 사용할 수 있습니다.
var globalBal = "var 변수"; let globalLet = "let 변수"; { let globalBlock = "block 변수"; };
글로벌 오브젝트에 작성하면
function showLocal() { var localVar = "var 변수"; let localLet = "let 변수"; { let blockLet = "block 변수"; }; };
함수에 작성
변수의 접근 권한으로 밖에서는 안의 변수를 사용하기 어렵지만, 안에서는 밖의 변수를 사용할 수 있는 점에서 스코프의 개념을 이해하는 것이 필요합니다.
console.log("music 변수:", music); var music = "음악"; // music 변수: undefined
try { console.log("music 변수:", music); } catch(e) { console.log("에러가 발생했습니다"); } let music = "음악"; // 에러가 발생했습니다
// 변수가 모두 아래에 작성되어 있습니다. console.log(globalVar); var globalVar = "var 변수"; // undefined
try { console.log(globalLet); } catch(e) { console.log("globalLet 인식 불가"); } let globalLet; console.log(globalLet); // globalLet 인식 불가 // undefined
{ console.log(variable); var variable = "var 변수"; let blockLet = "let 변수"; } // undefined
초기화 단계(코드를 실행하기 전)에서 정적 환경의 선언적 환경 레코드에 변수 이름을 바인딩합니다.
엔진에서는 이런 처리를 초기화자(Initializer)로 구분하고 있습니다.
변수 이름으로 식별자를 해결할 때
let 변수 선언을 실행하면 그때 값이 설정되며
따라서, 변수 선언을 실행한 후에는 변수가 값을 갖고 있으므로 변수를 인식할 수 있습니다.
엔진에서는 초기화자(Initializer)와 Binding List 메커니즘을 사용합니다.
변경 불가능한 변수 선언
구문: name1 [=value1], name2 [=value2]]
name1에 변수 이름 작성, 식별자로 사용
const sports = "축구"; try { sports = "농구"; } catch(e) { console.log("const 할당 불가"); }; // const 할당 불가
value1, value2에 초기값 작성
JS에서 상수는 대문자 사용이 관례입니다.
const bonus = 100; const POINT = 200;
우선 let이 아닌 const사용을 검토해야 합니다.
const 변수 전체를 바꿀 수는 없지만 Object의 프로퍼티 값을 바꿀 수는 있습니다.
const book = {title: "책"}; try { book = {title: "음악책"}; }catch(e) { console.log("const 전체 할당 불가"); } book.title = "미술책"; console.log(book.title); // const 전체 할당 불가 // 미술책
⇒ book에 값을 할당하면 const이기 때문에 에러가 발생합니다. 하지만, book내부의 title 프로퍼티 값은 변경할 수 있습니다.
const 변수 전체를 바꿀 수는 없지만 배열의 엘리먼트 값을 바꿀 수는 있습니다.
const book = ["책"]; try { book = ["음악책"]; } catch(e) { console.log("const 전체 할당 불가"); } book[0] = "미술책"; console.log(book[0]); // const 전체 할당 불가 // 미술책
⇒ book에 값을 할당하면 const이기 때문에 에러가 발생합니다. 하지만 book 배열의 엘리먼트 값은 바꿀 수 는 있습니다.