>  기사  >  웹 프론트엔드  >  자바스크립트 연구 노트 - 함수(6): 범위 및 네임스페이스_기본 지식

자바스크립트 연구 노트 - 함수(6): 범위 및 네임스페이스_기본 지식

WBOY
WBOY원래의
2016-05-16 16:30:461536검색

이전 소개에서 우리는 Javascript에는 블록 수준 범위가 없고 함수 수준 범위만 있다는 것을 이미 알고 있었습니다.

코드 복사 코드는 다음과 같습니다.

function test() { // 범위
for(var i = 0; i < 10; i ) { // 범위가 아님
             // 개수
}
console.log(i) // 10
}

또한 Javascript에는 명시적인 네임스페이스가 없습니다. 이는 모든 것이 전역 범위에서 정의된다는 의미입니다. 변수가 참조될 때마다 Javascript는 변수를 찾을 때까지 전체 전역 범위를 탐색합니다. 전체 전역 범위를 순회한 후에도 변수를 찾을 수 없으면 ReferenceError가 발생합니다.

이미지 설명을 입력해주세요

암시적 전역 변수

코드 복사 코드는 다음과 같습니다.

// 스크립트 A
foo = '42';
// 스크립트 B
var foo = '42'

위의 두 가지 예는 서로 다른 효과를 냅니다. 첫 번째 것은 전역 범위에서 foo 변수를 정의하고, 두 번째 것은 현재 범위에서 변수 foo를 정의합니다.
var 키워드를 사용하지 않으면 예상치 못한 결과가 발생한다는 점에 유의해야 합니다.

코드 복사 코드는 다음과 같습니다.

// 전역 범위
var foo = 42;
함수 테스트() {
// 로컬 범위
foo = 21;
}
테스트();
foo; // 21

함수 테스트에서는 foo 변수를 정의하는 데 var가 사용되지 않으므로 함수 외부의 전역 변수 foo를 덮어쓰게 됩니다. 큰 문제는 아닌 것 같지만, 수천 줄의 코드가 있으면 추적하기 어려운 버그가 될 수 있습니다.

코드 복사 코드는 다음과 같습니다.

// 전역 범위
var items = [/* 일부 목록 */];
for(var i = 0; i 하위 루프();
}
함수 하위 루프() {
// 하위 루프의 범위
for(i = 0; i < 10; i ) { // var 문이 누락되었습니다
              // 놀라운 일을 해내세요!
}
}

위의 예에서 외부 루프는 처음 실행될 때 중지됩니다. 왜냐하면 하위 루프 함수 내부의 변수 i가 외부 전역 변수 i를 덮어쓰기 때문입니다. 이 오류를 방지하려면 함수 내부에 var만 추가하면 되므로 변수를 정의할 때 var 키워드를 추가하는 것을 잊지 말아야 합니다. 외부 전역 변수에 실제로 영향을 미치고 싶지 않다면 말이죠.

지역변수

Javascript의 지역 변수는 두 가지 방법으로만 생성할 수 있습니다. 하나는 var 키워드를 통해 선언하는 것이고, 다른 하나는 함수의 형식 매개변수로 생성하는 것입니다.

코드 복사 코드는 다음과 같습니다.

// 전역 범위
var foo = 1;
var bar = 2;
var i = 2;
기능 테스트(i) {
// 함수 테스트의 로컬 범위
나는 = 5;
var foo = 3;
바 = 4;
}
테스트(10);

이때, 함수 test 내부의 변수 i와 foo는 지역 변수이고, bar는 외부 전역 변수 bar를 덮어쓰게 됩니다.

호이스팅

Javascript는 변수 선언을 호이스트합니다. 즉, var 표현식과 함수 선언이 모두 범위의 맨 위에 호이스트됩니다.

코드 복사 코드는 다음과 같습니다.

바();
var bar = function() {};
var someValue = 42;
테스트();
기능 테스트(데이터) {
만약 (거짓) {
         구 = 1;
} 그 밖의 {
      var goo = 2;
}
for(var i = 0; i       var e = 데이터[i];
}
}

위 코드를 실행하기 전에 var 표현식과 함수 테스트 선언이 상위로 승격되므로 프로그램이 정상적으로 실행되고 오류도 보고되지 않습니다.

코드 복사 코드는 다음과 같습니다.

// var 문이 여기로 이동되었습니다
var bar, someValue; // 기본값은 '정의되지 않음'
// 함수 선언도 위로 이동했습니다
기능 테스트(데이터) {
var goo, i, e; // 누락된 블록 범위가 여기로 이동됩니다
만약 (거짓) {
         구 = 1;
} 그 밖의 {
         구 = 2;
}
for(i = 0; i          e = 데이터[i];
}
}
bar(); // bar가 여전히 '정의되지 않음'이므로 TypeError로 실패합니다
someValue = 42; // 할당은 호이스팅에 영향을 받지 않습니다
바 = 함수() {};
테스트();

Javascript에는 블록 수준 범위가 없으므로 var 표현식이 향상될 뿐만 아니라 if 구조가 덜 직관적이게 됩니다.
위의 예에서는 if 가 글로벌 변수 goo에 대해 동작하는 것처럼 보이지만 실제로는 goo 변수가 승격되었기 때문에 수정되는 로컬 변수입니다.
호이스팅 규칙을 이해하지 못하면 다음 코드가 ReferenceError를 발생시킬 것이라고 생각할 수도 있습니다.

코드 복사 코드는 다음과 같습니다.

// SomeImportantThing이 초기화되었는지 확인
if (!SomeImportantThing) {
var SomeImportantThing = {};
}

물론 위 코드는 코드가 실행되기 전에 var 표현식이 최상위로 승격되었기 때문에 오류가 없습니다.

코드 복사 코드는 다음과 같습니다.

var SomeImportantThing;
// 다른 코드에서는 여기서 SomeImportantThing을 초기화할 수도 있고 초기화하지 않을 수도 있습니다
// 거기에 있는지 확인하세요
if (!SomeImportantThing) {
SomeImportantThing = {};
}

개선 사항을 매우 자세히 설명하는 @nightire Fan Ge의 블로그 게시물 "JavaScript 이해(2)"를 추천하고 싶습니다.
이름 확인 순서

함수 범위 내에서 foo 변수에 액세스하려고 하면 Javascript는 다음 순서로 찾습니다.

현재 범위에 var foo 정의가 있는지 여부입니다.
함수 매개변수에 foo 변수가 있는지 여부.
함수 자체의 이름이 foo인지 여부.
외부 도메인으로 이동하여 첫 번째 부분부터 검색합니다.
네임스페이스

가장 일반적인 문제 중 하나는 전역 범위가 하나뿐인 Javascript로 인해 발생하는 이름 충돌입니다. 하지만 이 문제는 익명의 외부 함수를 통해 해결될 수 있습니다.

코드 복사 코드는 다음과 같습니다.

(함수() {
// 자체 포함된 "네임스페이스"
window.foo = 함수() {
                // 노출된 클로저
};
})(); // 즉시 함수 실행

위 예시의 익명 함수는 표현식으로 간주되어 실행됩니다.

코드 복사 코드는 다음과 같습니다.

( // 괄호 안의 함수를 평가합니다
함수() {}
) // 그리고 함수 객체를 반환합니다
() // 평가 결과 호출

물론 구조는 다르지만 효과는 동일한 다른 방식으로 함수 표현식을 호출할 수도 있습니다.

코드 복사 코드는 다음과 같습니다.

//
를 직접 호출하기 위한 몇 가지 다른 스타일 !함수(){}()
함수(){}()
(함수(){}());
// 등등...

요약

익명의 외부 함수를 사용하여 코드를 공백으로 캡슐화하는 것이 좋습니다. 이렇게 하면 네임스페이스 충돌을 해결할 수 있을 뿐만 아니라 프로그램의 모듈화도 촉진할 수 있습니다.
또한 전역 변수를 사용하는 것은 유지 관리 비용이 많이 들고 오류가 발생하기 쉽기 때문에 좋은 방법이 아닙니다.

네임스페이스 유형, 함수, 변수, 템플릿 등은 모두 엔터티에 속합니다.
엔터티의 주요 공통점은 이름을 가질 수 있다는 것입니다. (또한 라벨에도 이름이 있을 수 있지만 개체는 아닙니다.)
네임스페이스 범위는 블록 범위, 클래스 범위, 함수 프로토타입 범위 및 함수 범위(레이블에만 유효)와 함께 범위 유형에 대한 일반적인 용어입니다. 네임스페이스 내에 선언된 이름은 네임스페이스 범위에 있습니다. 전역 이름은 암시적 전역 네임스페이스 범위에 속하는 것으로 간주됩니다.

네임스페이스의 역할은 실제로 범위이지만 단순한 범위와는 다릅니다. 동일한 네임스페이스를 여러 위치에서 여러 번 선언할 수 있지만 내용을 다시 정의할 수는 없습니다. 공간은 표준과 마찬가지로 어디에서나 매크로 정의를 사용할 수 있습니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.