웹 프론트엔드 JS 튜토리얼 JavaScript 고급 시리즈 - 범위 및 네임스페이스

JavaScript 고급 시리즈 - 범위 및 네임스페이스

Feb 08, 2017 am 09:35 AM

  • 암시적 전역 변수

  • 지역 변수

  • 변수 선언 호이스팅(Hoisting)

  • 이름 확인 순서

  • 네임스페이스

  • 결론

JavaScript는 지원하지만 중괄호 쌍으로 생성된 코드 조각은 블록 수준 범위를 지원하지 않고 함수 범위만 지원합니다.

function test() { // 一个作用域
    for(var i = 0; i < 10; i++) { // 不是一个作用域
        // count
    }
    console.log(i); // 10
}
로그인 후 복사

번역자 주의 사항: 반환 개체의 왼쪽 대괄호와 return이 같은 줄에 있지 않으면 오류가 발생합니다.

(참고: 대입문이 아니라 반환 표현식 또는 함수 매개변수에 있는 경우 {...}는 리터럴 구문 분석이 아닌 코드 세그먼트로 구문 분석됩니다. 자동 세미콜론 삽입을 고려하면 미묘한 오류가 발생할 수 있습니다.)

// 译者注:下面输出 undefined
function add(a, b) {
    return 
        a + b;
}
console.log(add(1, 2));
로그인 후 복사

JavaScript에는 명시적인 네임스페이스 정의가 없습니다. 즉, 모든 객체는 아래에 정의됩니다. 전역적으로 공유되는 네임스페이스.

변수가 참조될 때마다 JavaScript는 변수를 찾을 때까지 전체 범위를 위쪽으로 탐색합니다. 전역 범위에 도달했지만 여전히 변수를 찾을 수 없으면 ReferenceError 예외가 발생합니다.

암시적 전역 변수

// 脚本 A
foo = &#39;42&#39;;

// 脚本 B
var foo = &#39;42&#39;
로그인 후 복사

위의 두 스크립트는 효과가 다릅니다. 스크립트 A는 전역 범위에서 foo 변수를 정의하고, 스크립트 B는 현재 범위에서 변수 foo를 정의합니다.

다시 한번 말씀드리지만, var를 사용하지 않고 변수를 선언하면 암시적 전역 변수가 생성됩니다.

// 全局作用域
var foo = 42;
function test() {
    // 局部作用域
    foo = 21;
}
test();
foo; // 21
로그인 후 복사

함수 테스트 내에서 var 키워드를 사용하지 않고 foo 변수를 선언하면 동일한 이름으로 외부 변수를 덮어쓰게 됩니다. 처음에는 큰 문제가 아닌 것처럼 보일 수도 있지만 수천 줄의 코드가 있는 경우 var를 사용하지 않고 변수를 선언하면 추적하기 어려운 버그가 발생할 수 있습니다.

// 全局作用域
var items = [/* 数组 */];
for(var i = 0; i < 10; i++) {
    subLoop();
}

function subLoop() {
    // subLoop 函数作用域
    for(i = 0; i < 10; i++) { // 没有使用 var 声明变量
        // 干活
    }
}
로그인 후 복사

subLoop가 전역 변수 i를 덮어쓰기 때문에 subLoop에 대한 첫 번째 호출 후에 외부 루프가 종료됩니다. 두 번째 for 루프에서 var를 사용하여 변수를 선언하면 이 오류를 피할 수 있습니다. 외부 범위에 영향을 미치는 바람직한 동작이 아닌 이상 변수를 선언할 때 var 키워드를 생략하지 마십시오.

지역 변수

JavaScript의 지역 변수는 두 가지 방법으로만 선언할 수 있습니다. 하나는 함수 매개변수로 선언하고 다른 하나는 var 키워드를 통해 선언합니다.

// 全局变量
var foo = 1;
var bar = 2;
var i = 2;

function test(i) {
    // 函数 test 内的局部作用域
    i = 5;

    var foo = 3;
    bar = 4;
}
test(10);
로그인 후 복사

foo와 i는 test 함수 내의 지역 변수이며 bar에 할당하면 전역 범위에서 동일한 이름으로 변수를 덮어씁니다.

변수 선언 호이스팅(Hoisting)

자바스크립트는 변수 선언을 호이스팅합니다. 즉, var 표현식과 함수 선언이 모두 현재 범위의 맨 위로 끌어올려집니다.

bar();
var bar = function() {};
var someValue = 42;

test();
function test(data) {
    if (false) {
        goo = 1;

    } else {
        var goo = 2;
    }
    for(var i = 0; i < 100; i++) {
        var e = data[i];
    }
}
로그인 후 복사

위 코드는 실행 전 변환됩니다. JavaScript는 var 표현식과 함수 선언을 현재 범위의 맨 위로 끌어올립니다.

// var 表达式被移动到这里
var bar, someValue; // 缺省值是 &#39;undefined&#39;

// 函数声明也会提升
function test(data) {
    var goo, i, e; // 没有块级作用域,这些变量被移动到函数顶部
    if (false) {
        goo = 1;

    } else {
        goo = 2;
    }
    for(i = 0; i < 100; i++) {
        e = data[i];
    }
}

bar(); // 出错:TypeError,因为 bar 依然是 &#39;undefined&#39;
someValue = 42; // 赋值语句不会被提升规则(hoisting)影响
bar = function() {};

test();
로그인 후 복사

블록 범위가 없으면 var 표현식이 루프 내부에서 외부로 이동될 뿐만 아니라 일부 if 표현식을 읽기가 더 어려워집니다.

원래 코드에서 if 표현식은 전역 변수 goo를 수정하는 것처럼 보이지만 실제로는 승격 규칙이 적용된 후에 지역 변수를 수정합니다.

호이스팅에 대한 지식이 없으면 다음 코드는 ReferenceError 예외를 발생시키는 것으로 나타납니다.

// 检查 SomeImportantThing 是否已经被初始化
if (!SomeImportantThing) {
    var SomeImportantThing = {};
}
로그인 후 복사

실제로 위 코드는 var 표현식이 전역 범위의 맨 위로 끌어올려지기 때문에 제대로 작동합니다.

var SomeImportantThing;

// 其它一些代码,可能会初始化 SomeImportantThing,也可能不会

// 检查是否已经被初始化
if (!SomeImportantThing) {
    SomeImportantThing = {};
}
로그인 후 복사

번역자 주: Nettuts+ 웹사이트에 호이스팅을 소개하는 기사가 있는데, 그 안에 있는 코드가 매우 유익합니다.

// 译者注:来自 Nettuts+ 的一段代码,生动的阐述了 JavaScript 中变量声明提升规则
var myvar = &#39;my value&#39;;  

(function() {  
    alert(myvar); // undefined  
    var myvar = &#39;local value&#39;;  
})();
로그인 후 복사

이름 확인 순서


전역 범위를 포함하여 JavaScript의 모든 범위에는 현재 개체를 가리키는 특별한 이름이 있습니다. 함수 범위에는 함수에 전달된 매개변수를 포함하는 기본 변수 인수도 있습니다. 예를 들어, 함수 내의 foo 변수에 액세스할 때 JavaScript는 다음 순서로 검색합니다.

  1. 현재 범위에 var foo 정의가 있는지 여부.

  2. 함수 형식 매개변수가 foo 이름을 사용하는지 여부입니다.

  3. 함수 자체를 foo라고 하는지.

  4. 이전 범위로 돌아가서 #1부터 다시 시작하세요.

네임스페이스

전역 범위가 하나만 있을 때 발생하는 일반적인 실수는 이름 충돌입니다. JavaScript에서는 익명 래퍼를 사용하여 이 문제를 쉽게 해결할 수 있습니다.

(참고: 사용자 정의 인수는 기본 인수 개체 생성을 방지합니다.)

(function() {
    // 函数创建一个命名空间

    window.foo = function() {
        // 对外公开的函数,创建了闭包
    };

})(); // 立即执行此匿名函数
로그인 후 복사

익명 함수는 표현식으로 간주되므로 호출 가능성을 위해 먼저 실행됩니다.

( // 小括号内的函数首先被执行
function() {}
) // 并且返回函数对象
() // 调用上面的执行结果,也就是函数对象
로그인 후 복사

함수 표현식을 호출하는 다른 방법이 있습니다. 예를 들어 다음 두 메서드는 구문이 다르지만 효과는 완전히 동일합니다.

// 另外两种方式
+function(){}();
(function(){}());
로그인 후 복사

결론


네임스페이스를 생성하려면 익명 래퍼(번역자 주: 자체 실행 익명 함수)를 사용하는 것이 좋습니다. 이는 이름 충돌을 방지할 뿐만 아니라 프로그램의 모듈화를 촉진합니다.

또한 전역 변수를 사용하는 것은 나쁜 습관으로 간주됩니다. 이러한 코드는 오류가 발생하기 쉽고 유지 관리 비용이 많이 듭니다.

위는 JavaScript 고급 시리즈의 내용입니다. - 범위 및 네임스페이스 관련 내용은 PHP 중국어 홈페이지(www.php.cn)를 참고해주세요!


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

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

C 언어에서 typedef 구조체 사용법 C 언어에서 typedef 구조체 사용법 May 09, 2024 am 10:15 AM

typedef struct는 C 언어에서 구조 사용을 단순화하기 위해 구조 유형 별칭을 만드는 데 사용됩니다. 구조 별칭을 지정하여 기존 구조에 새 데이터 유형의 별칭을 지정합니다. 향상된 가독성, 코드 재사용 및 유형 확인 등의 이점이 있습니다. 참고: 별칭을 사용하기 전에 구조를 정의해야 합니다. 별칭은 프로그램에서 고유해야 하며 선언된 범위 내에서만 유효해야 합니다.

Java에서 예상되는 변수를 해결하는 방법 Java에서 예상되는 변수를 해결하는 방법 May 07, 2024 am 02:48 AM

Java의 변수 예상 값 예외는 변수 초기화, null 값 사용, 지역 변수 범위 파악을 통해 해결할 수 있습니다.

js 클로저의 장점과 단점 js 클로저의 장점과 단점 May 10, 2024 am 04:39 AM

JavaScript 클로저의 장점에는 변수 범위 유지, 모듈식 코드 활성화, 실행 지연 및 이벤트 처리가 포함됩니다. 단점에는 메모리 누수, 복잡성 증가, 성능 오버헤드 및 범위 체인 효과가 포함됩니다.

C++에서 include의 의미는 무엇입니까? C++에서 include의 의미는 무엇입니까? May 09, 2024 am 01:45 AM

C++의 #include 전처리기 지시문은 외부 소스 파일의 내용을 현재 소스 파일에 삽입하고 해당 내용을 현재 소스 파일의 해당 위치에 복사합니다. 표준 입출력 함수를 포함하기 위한 #include <iostream>과 같이 코드에 필요한 선언이 포함된 헤더 파일을 포함하는 데 주로 사용됩니다.

C++ 스마트 포인터: 수명 주기에 대한 포괄적인 분석 C++ 스마트 포인터: 수명 주기에 대한 포괄적인 분석 May 09, 2024 am 11:06 AM

C++ 스마트 포인터의 수명 주기: 생성: 스마트 포인터는 메모리가 할당될 때 생성됩니다. 소유권 이전: 이동 작업을 통해 소유권을 이전합니다. 해제: 스마트 포인터가 범위를 벗어나거나 명시적으로 해제되면 메모리가 해제됩니다. 객체 소멸: 가리키는 객체가 소멸되면 스마트 포인터는 유효하지 않은 포인터가 됩니다.

C++에서 함수 정의와 호출을 중첩할 수 있나요? C++에서 함수 정의와 호출을 중첩할 수 있나요? May 06, 2024 pm 06:36 PM

할 수 있다. C++에서는 중첩된 함수 정의 및 호출을 허용합니다. 외부 함수는 내장 함수를 정의할 수 있고 내부 함수는 범위 내에서 직접 호출할 수 있습니다. 중첩된 함수는 캡슐화, 재사용성 및 범위 제어를 향상시킵니다. 그러나 내부 함수는 외부 함수의 로컬 변수에 직접 액세스할 수 없으며 반환 값 유형은 외부 함수 선언과 일치해야 합니다.

js에서 이것이 다음을 가리키는 여러 가지 상황이 있습니다. js에서 이것이 다음을 가리키는 여러 가지 상황이 있습니다. May 06, 2024 pm 02:03 PM

JavaScript에서 이 포인팅 유형은 다음을 포함합니다: 1. 전역 객체, 2. 함수 호출, 3. 생성자 호출, 5. 화살표 함수(외부 상속). 또한, 바인딩(), call() 및 apply() 메서드를 사용하여 이것이 가리키는 내용을 명시적으로 설정할 수 있습니다.

vue에서 let과 var의 차이점 vue에서 let과 var의 차이점 May 08, 2024 pm 04:21 PM

Vue에서는 let과 var 사이에 변수를 선언할 때 범위에 차이가 있습니다. 범위: var에는 전역 범위가 있고 let에는 블록 수준 범위가 있습니다. 블록 수준 범위: var는 블록 수준 범위를 생성하지 않으며, 블록 수준 범위를 생성합니다. 재선언: var는 동일한 범위에 있는 변수의 재선언을 허용하지만 let은 허용하지 않습니다.

See all articles