⚠️ 오래된 스크립트를 읽는 데 도움을 주는 글입니다.
◾️ 변수 선언 방법
- let
- const
- var
◾️ let과 const는 렉시컬 환경 측면에서 정확히 같은 방식으로 동작한다.
◾️ var는 초기 자바스크립트 구현 방식 때문에 전혀 다른 방식으로 동작한다.
function sayHi () {
var phrase = "Hello"; // 'let'대신 'var'를 사용해 지역 변수를 선언
console.log(phrase); //Hello
}
sayHi(); // Hello
console.log(phrase); // Error, phrase is not defined
var는 블록 스코프가 없다.
◾️ var로 선언한 변수의 스코프는 함수 스코프이거나 전역 스코프이다.
◾️ 블록 기준으로 스코프가 생기지 않기 때문에 블록 밖에서 접근 가능하다.
if(true) {
var test = true;
}
console.log(test); // true
◾️ var는 코드 블록을 무시하기 때문에 test는 전역 변수가 된다. 전역 스코프에서 test에 접근할 수 있다.
◾️ var 대신 let으로 선언했다면 에러가 발생한다. (if문 안에서만 접근할 수 있다. )
if(true) {
let test = true;
}
console.log(test); // Error: test is not defined
◾️ 반복문에서 var → 반복문이 종료되었지만 i는 전역 변수이기 때문에 접근이 가능하다.
for(var i = 0; i < 10; i++) {
console.log(i); // 0, 1, ... 9
}
console.log(i); // 10
◾️ 코드 블록이 함수 안에 있다면, var는 함수 레벨 변수가 된다.
function sayHi() {
if(true){
var phrase = "Hello";
}
console.log(phrase); // Hello
}
sayHi();
console.log(phrase); // Error: phrase is not defined
◾️ var는 if, for 등의 코드 블록을 관통한다. 오래전의 자바스크립트에선 블록 수준 렉시컬 환경이 만들어지지 않았기 때문
함수 시작과 함께 처리되는 var
◾️ var 선언은 함수가 시작될 때 처리된다.
◾️ 전역에서 선언한 변수라면 스크립트가 시작될 때 처리된다.
◾️ 함수 본문 내에서 var로 선언한 변수는 선언 위치와 상관없이 함수 본문이 시작되는 지점에서 정의된다 (단, 변수가 중첩 함수 내에서 정의 되지 않아야 이 규칙이 적용됨)
◾️ 3가지 예시 모두 동일하게 동작한다.
function sayHi() {
phrase = "Hello";
console.log(phrase); // Hello
var phrase;
}
sayHi();
function sayHi() {
var phrase;
phrase = "Hello";
console.log(phrase); // Hello
}
sayHi();
function sayHi() {
phrase = "Hello"; // (*)
if (false) {
var phrase;
}
console.log(phrase);
}
sayHi();
◾️ 호이스팅(hoisting) : 변수가 끌어올려 지는 현상
◾️ var로 선언한 모든 변수는 함수의 최상위로 끌어 올려진다.
◾️ if(false) 블록 안 코드는 절대 실행되지 않지만, 호이스팅에 전혀 영향을 주지 않는다.
◾️ if 내부의 var는 함수 sayHi의 시작부분에서 처리되므로 *로 표시한 줄에서 phrase는 이미 정의된 상태이다.
✳️ 선언은 호이스팅 되지만 할당은 호이스팅 되지 않는다.
function sayHi() {
console.log(phrase);
var phrase = "Hello";
}
sayHi();
◾️ var phrase = "Hello"행에선 두가지 일이 일어난다.
- 변수 선언(var)
- 변수에 값을 할당(=)
◾️ 변수 선언은 함수 실행이 시작될 때 처리 되지만(호이스팅) 할당은 호이스팅 되지 않기 때문에 할당 관련 코드에서 처리된다.
function sayHi() {
var phrase; // 선언 → 함수 시작 시 처리
console.log(phrase); // undefined
phrase = "Hello"; // 할당 → 실행 흐름이 코드에 도달했을 때 처리
}
sayHi();
◾️ 모든 var 선언은 함수 시작 시 처리되기 때문에, var로 선언한 변수는 어디서든 참조할 수 있다.
◾️ 변수에 값을 할당하기 전까지는 undefined
즉시 실행 함수 표현식
◾️ var도 블록 레벨 스코프를 가질 수 있게 만들어진 즉시 실행 함수 표현식(IIFE; immediately-invoked function expressions)
(function() {
let message = "Hello";
console.log(message); // Hello
})();
◾️ 함수 표현식이 만들어지고 바로 호출되면서, 해당 함수가 바로 실행된다.
◾️ 즉시 실행 함수 형태 : (function () { ... })
// 함수를 선언과 동시에 실행하려고 함
function() { // <-- Error: Function statements require a function name
let message = "Hello";
console.log(message); // Hello
}();
◾️ 자바스크립트는 function이라는 키워드를 만나면 함수 선언문이 시작될 것이라 예상한다. 그런데 함수 선언문으로 함수를 만들 땐 반드시 함수의 이름이 있어야 하기 때문에 괄호로 감싸지 않으면 에러가 발생한다.
// Error
function go() {
}(); // ← 함수 선언문은 선언 즉시 호출할 수 없다.
◾️ 자바스크립트는 함수 선언문으로 정의한 함수를 정의와 동시에 바로 호출하는 것을 허용하지 않는다.
◾️ 자바스크립트가 함수 표현식이라고 인식하게 해주는 다른 방법들(모던 자바스크립트에선 이렇게 코드를 작성할 필요가 없다.)
// IIFE를 만드는 방법
(function() {
alert("함수를 괄호로 둘러싸기");
})();
(function() {
alert("전체를 괄호로 둘러싸기");
}());
!function() {
alert("표현식 앞에 비트 NOT 연산자 붙이기");
}();
+function() {
alert("표현식 앞에 단항 덧셈 연산자 붙이기");
}();
📝 요약
◽️ var로 선언한 변수는 let이나 const로 선언한 변수와 다른 두 가지 주요한 특성을 보인다.
1. var로 선언한 변수는 블록 스코프가 아닌 함수 수준 스코프를 갖는다.
2. var 선언은 함수가 시작되는 시점(전역 공간에선 스크립트가 시작되는 시점)에서 처리된다.
📝 오늘 새롭게 배운 내용 📝
✅ var는 함수 스코프 let과 const는 블록 스코프
✅ var는 호이스팅(선언 하면 최상위로 끌어올려진다) 된다
✅ 선언만 호이스팅 되고 할당은 실행 흐름 시점에서 이루어진다. (보통 선언과 할당을 동시에 해서 몰랐다..)
✅ 변수는 블록 레벨 스코프를 갖는 게 좋다.
✅ 실행 되지 않는 반복문 안에 있는 변수에 접근할 수 있었다니...
✅ let과 const를 쓰자!!!!
📌 [JAVASCRIPT_INFO 오래된 'var']
'모던 자바스크립트' 카테고리의 다른 글
6.6 객체로서의 함수와 기명 함수 표현식 (0) | 2020.08.24 |
---|---|
6.5 전역 객체 (0) | 2020.08.22 |
6.3 변수의 스코프 (0) | 2020.08.20 |
6.2 나머지 매개변수와 전개 문법 (0) | 2020.08.19 |
6.1 재귀와 스택 (0) | 2020.08.15 |