이 글은 오래된 스크립트를 이해하기 위한 것입니다.
이 문서의 정보는 이전 스크립트를 이해하는 데 유용합니다.
그것은 우리가 새로운 코드를 작성하는 방식이 아닙니다.
변수에 관한 첫 번째 장에서 우리는 변수 선언의 세 가지 방법을 언급했습니다.
let
const
var
var
선언은 let
과 유사합니다. 대부분의 경우 let
var
로 대체하거나 그 반대로 대체하여 제대로 작동할 것으로 예상할 수 있습니다.
var message = "안녕하세요"; 경고(메시지); // 안녕
그러나 내부적으로 var
아주 옛날부터 시작된 매우 다른 짐승입니다. 일반적으로 현대 스크립트에서는 사용되지 않지만 이전 스크립트에는 여전히 숨어 있습니다.
그러한 스크립트를 만날 계획이 없다면 이 장을 건너뛰거나 연기할 수도 있습니다.
반면, 이상한 오류를 방지하려면 var
에서 let
으로 이전 스크립트를 마이그레이션할 때 차이점을 이해하는 것이 중요합니다.
var
로 선언된 변수는 함수 범위 또는 전역 범위입니다. 블록을 통해 볼 수 있습니다.
예를 들어:
만약 (참) { var 테스트 = true; // "let" 대신 "var"를 사용합니다. } 경고(테스트); // true, 변수는 if 이후에도 유지됩니다.
var
코드 블록을 무시하므로 전역 변수 test
있습니다.
var test
대신 let test
사용하면 변수는 다음과 if
에만 내부에서 볼 수 있습니다.
만약 (참) { 테스트 = true로 두십시오. // "렛"을 사용하세요 } 경고(테스트); // ReferenceError: 테스트가 정의되지 않았습니다.
루프에서도 마찬가지입니다. var
블록 또는 루프 로컬일 수 없습니다.
for (var i = 0; i < 10; i++) { var 하나 = 1; // ... } 경고(i); // 10, "i"는 루프 후에 표시되며 전역 변수입니다. 경고(하나); // 1, "one"은 루프 후에 표시되며 전역 변수입니다.
코드 블록이 함수 안에 있으면 var
함수 수준 변수가 됩니다.
함수 sayHi() { 만약 (참) { var 구문 = "안녕하세요"; } 경고(문구); // 작동 } 안녕하세요(); 경고(문구); // ReferenceError: 구문이 정의되지 않았습니다.
보시다시피 var
if
, for
또는 기타 코드 블록을 관통합니다. 그 이유는 오래 전 JavaScript에서는 블록에 어휘 환경이 없었고 var
그 잔재이기 때문입니다.
동일한 범위에서 let
두 번 사용하여 동일한 변수를 선언하면 오류가 발생합니다.
사용자를 보자; 사용자를 보자; // 구문 오류: 'user'가 이미 선언되었습니다.
var
사용하면 변수를 여러 번 다시 선언할 수 있습니다. 이미 선언된 변수와 함께 var
사용하면 그냥 무시됩니다.
var user = "피트"; var user = "존"; // 이 "var"는 아무 작업도 수행하지 않습니다(이미 선언됨). // ...오류가 발생하지 않습니다. 경고(사용자); // 존
var
선언은 함수가 시작될 때(또는 전역의 경우 스크립트가 시작될 때) 처리됩니다.
즉, var
변수는 정의가 어디에 있든 관계없이 함수의 시작 부분부터 정의됩니다(정의가 중첩된 함수에 없다고 가정).
따라서 이 코드는 다음과 같습니다.
함수 sayHi() { 문구 = "안녕하세요"; 경고(문구); var 문구; } 안녕하세요();
...기술적으로 다음과 동일합니다(위의 var phrase
로 이동됨).
함수 sayHi() { var 문구; 문구 = "안녕하세요"; 경고(문구); } 안녕하세요();
...또는 다음과 같이 해도 됩니다(코드 블록은 무시된다는 점을 기억하세요).
함수 sayHi() { 문구 = "안녕하세요"; // (*) 만약 (거짓) { var 문구; } 경고(문구); } 안녕하세요();
사람들은 또한 모든 var
함수의 최상위로 "호이스팅"(상승)되기 때문에 이러한 동작을 "호이스팅"(상승)이라고 부릅니다.
따라서 위의 예에서는 if (false)
분기가 실행되지 않지만 이는 중요하지 않습니다. 그 안의 var
함수 시작 부분에서 처리되기 때문에 (*)
순간에는 변수가 존재하게 됩니다.
선언은 호이스팅되지만 할당은 호이스팅되지 않습니다.
이는 다음 예를 통해 가장 잘 설명됩니다.
함수 sayHi() { 경고(문구); var 구문 = "안녕하세요"; } 안녕하세요();
var phrase = "Hello"
줄에는 두 가지 작업이 있습니다.
변수 선언 var
변수 할당 =
.
선언은 함수 실행 시작 시("호이스팅") 처리되지만 할당은 항상 나타나는 위치에서 작동합니다. 따라서 코드는 기본적으로 다음과 같이 작동합니다.
함수 sayHi() { var 문구; // 선언은 시작 시 작동합니다... 경고(문구); // 한정되지 않은 문구 = "안녕하세요"; // ...할당 - 실행이 도달할 때. } 안녕하세요();
모든 var
선언은 함수 시작 시 처리되므로 어디에서나 참조할 수 있습니다. 그러나 변수는 할당 전까지 정의되지 않습니다.
위의 두 예 모두 변수 phrase
존재하므로 alert
오류 없이 실행됩니다. 하지만 해당 값은 아직 할당되지 않았으므로 undefined
표시됩니다.
과거에는 var
만 있었고 블록 수준 가시성이 없었기 때문에 프로그래머는 이를 에뮬레이트하는 방법을 고안했습니다. 그들이 한 일은 "즉시 호출 함수 표현식"(IIFE로 약칭)이라고 불렸습니다.
오늘날 우리가 사용해야 하는 것은 아니지만 오래된 스크립트에서 찾을 수 있습니다.
IIFE는 다음과 같습니다:
(기능() { var message = "안녕하세요"; 경고(메시지); // 안녕하세요 })();
여기에서는 함수 표현식이 생성되어 즉시 호출됩니다. 따라서 코드는 즉시 실행되며 자체 개인 변수를 갖습니다.
함수 표현식은 괄호 (function {...})
로 래핑됩니다. 왜냐하면 JavaScript 엔진이 메인 코드에서 "function"
발견하면 이를 함수 선언의 시작으로 이해하기 때문입니다. 그러나 함수 선언에는 이름이 있어야 하므로 이러한 종류의 코드에서는 오류가 발생합니다.
// 함수를 선언하고 즉시 호출하려고 시도합니다. function() { // <-- SyntaxError: 함수 문에는 함수 이름이 필요합니다. var message = "안녕하세요"; 경고(메시지); // 안녕하세요 }();
"좋아, 이름을 추가하자"라고 말하더라도 JavaScript는 함수 선언이 즉시 호출되는 것을 허용하지 않기 때문에 작동하지 않습니다.
// 아래 괄호로 인해 구문 오류가 발생했습니다. 함수 이동() { }(); // <-- 함수 선언을 즉시 호출할 수 없습니다.
따라서 함수 주위의 괄호는 함수가 다른 표현식의 컨텍스트에서 생성되므로 함수 표현식이라는 사실을 JavaScript에 표시하기 위한 트릭입니다. 이름이 필요하지 않으며 즉시 호출할 수 있습니다.
함수 표현식을 의미한다는 것을 JavaScript에 알리는 괄호 외에도 다른 방법이 있습니다.
// IIFE 생성 방법 (기능() { Alert("함수 주위에 괄호"); })(); (기능() { Alert("전체를 괄호로 묶습니다."); }()); !기능() { Alert("비트 NOT 연산자가 표현식을 시작합니다."); }(); +함수() { Alert("단항 더하기가 표현식을 시작합니다."); }();
위의 모든 경우에 함수 표현식을 선언하고 즉시 실행합니다. 다시 한 번 말씀드리자면, 요즘에는 그런 코드를 작성할 이유가 없습니다.
let/const
와 비교하여 var
에는 두 가지 주요 차이점이 있습니다.
var
변수에는 블록 범위가 없으며 가시성 범위는 현재 함수 또는 함수 외부에서 선언된 경우 전역으로 지정됩니다.
var
선언은 함수 시작 시 처리됩니다(전역의 경우 스크립트 시작).
전역 개체와 관련하여 아주 사소한 차이점이 하나 더 있는데, 이에 대해서는 다음 장에서 다루겠습니다.
이러한 차이점은 대부분의 let
보다 var
더 나쁘게 만듭니다. 블록 수준 변수는 정말 대단한 것입니다. 그렇기 때문에 오래 전에 표준에 let
도입되었으며 이제는 변수를 선언하는 주요 방법( const
와 함께)입니다.