JavaScript에서 변수의 범위는 무엇입니까?


2011

자바 스크립트에서 변수의 범위는 무엇입니까? 함수 외부와 반대로 내부와 동일한 범위를 가지고 있습니까? 아니면 중요합니까? 또한 전역 적으로 정의 된 변수는 어디에 저장됩니까?


4
다음은 이 문제를 명심해야 할 또 다른 멋진 링크입니다 . " 자바 스크립트 범위 및 폐쇄 설명 "
풀 스택 소프트웨어 엔지니어

9
여기에 아주 잘 설명 된 기사가 있습니다. Javascript 변수 범위에 대해 알아야 할 모든 것
Saurab Parakh

2
앞서 언급 한 카일 심슨의 전자 책은 Github에서에서 읽을 수 있으며, 그것은 당신이 자바 스크립트 스코프 및 폐쇄에 대해 알아야 할 모든 것을 알려줍니다. 당신은 여기에서 찾을 수 있습니다 github.com/getify/You-Dont-Know-JS/blob/master/... 의 그것의 일부 "당신은 JS 몰라"책 시리즈 를 알고 싶습니다 모두를 위해 중대하다, 자바 스크립트에 대해 자세히 알아보세요.
3rik82

답변:


2534

TLDR

JavaScript에는 어휘 (정적이라고도 함) 범위 지정 및 클로저가 있습니다. 즉, 소스 코드를 보면 식별자의 범위를 알 수 있습니다.

네 가지 범위는 다음과 같습니다.

  1. 글로벌-모든 것으로 표시
  2. 기능-기능 (및 해당 하위 기능 및 블록) 내에서 표시
  3. 블록-블록 (및 해당 하위 블록)에 표시
  4. 모듈-모듈 내에서 표시

전역 및 모듈 범위의 특수한 경우를 제외하고 변수는 var(함수 범위), let(블록 범위) 및 const(블록 범위)를 사용하여 선언됩니다 . 대부분의 다른 형태의 식별자 선언은 엄격 모드에서 블록 범위를 갖습니다.

개요

범위는 식별자가 유효한 코드베이스의 영역입니다.

어휘 환경은 식별자 이름과 관련된 값 사이의 매핑입니다.

범위는 어휘 환경의 연결된 중첩으로 구성되며, 중첩의 각 레벨은 상위 실행 컨텍스트의 어휘 환경에 해당합니다.

이러한 연결된 어휘 환경은 범위 "체인"을 형성합니다. 식별자 확인은이 체인을 따라 일치하는 식별자를 검색하는 프로세스입니다.

식별자 해상도는 한 방향으로 만 발생합니다 : 바깥 쪽. 이러한 방식으로 외부 어휘 환경은 내부 어휘 환경을 "볼"수 없습니다.

JavaScript 에서 식별자범위 를 결정하는 데는 세 가지 관련 요소가 있습니다 .

  1. 식별자 선언 방법
  2. 식별자가 선언 된 곳
  3. 엄격 모드 인지 엄격하지 않은 모드 인지 여부

식별자를 선언 할 수있는 몇 가지 방법 :

  1. var, letconst
  2. 기능 매개 변수
  3. 캐치 블록 매개 변수
  4. 함수 선언
  5. 명명 된 함수 표현식
  6. 전역 객체에 대해 암시 적으로 정의 된 속성 (예 : var엄격하지 않은 모드에서는 누락 )
  7. import 진술
  8. eval

위치 식별자 중 일부를 선언 할 수 있습니다.

  1. 글로벌 컨텍스트
  2. 기능 바디
  3. 보통 블록
  4. 제어 구조의 상단 (예 : 루프, if, while 등)
  5. 제어 구조체
  6. 모듈

선언 스타일

var

전역 컨텍스트에서 직접 선언 된 경우를 제외하고 사용하여 선언 된 식별자 에는 전역 범위에서 특성으로 추가되고 전역 var 범위가있는 함수 범위가 있습니다 . eval기능에 사용하기위한 별도의 규칙이 있습니다.

let과 const

식별자를 사용하여 선언 letconst 블록 범위를 가지고 는 그들이 글로벌 범위를 가지고있는 경우에 국제적인 맥락에서 직접 선언 할 때 그렇다.

참고 : let, constvar 모든 게양된다 . 이는 논리적 정의 위치가 둘러싸는 범위 (블록 또는 기능)의 최상위임을 의미합니다. 그러나 변수는 useing 선언 letconst읽거나 제어 소스 코드에 선언의 지점을 통과 할 때까지 할당 할 수 없습니다. 임시 기간은 임시 데드 존이라고합니다.

function f() {
    function g() {
        console.log(x)
    }
    let x = 1
    g()
}
f() // 1 because x is hoisted even though declared with `let`!

함수 매개 변수 이름

함수 매개 변수 이름은 함수 본문의 범위입니다. 이것에는 약간의 복잡성이 있습니다. 기본 인수로 선언 된 함수는 함수 본문이 아닌 매개 변수 목록 위에 닫힙니다 .

함수 선언

함수 선언은 엄격 모드의 블록 범위와 엄격하지 않은 모드의 함수 범위를 갖습니다. 참고 : 엄격하지 않은 모드는 서로 다른 브라우저의 기발한 역사적 구현을 ​​기반으로하는 복잡한 규칙입니다.

명명 된 함수 표현식

명명 된 함수 표현식은 그 자체로 범위가 지정됩니다 (예 : 재귀 목적으로).

전역 객체에 대해 암시 적으로 정의 된 속성

엄격하지 않은 모드에서는 전역 개체가 범위 체인의 최상위에 위치하기 때문에 전역 개체에 대해 암시 적으로 정의 된 속성에 전역 범위가 있습니다. 엄격 모드에서는 허용되지 않습니다.

평가

에서는 eval문자열 변수 사용 선언 var한다면, 현재 범위에 배치된다 또는 eval간접적으로 사용되는 전역 객체 건물.

다음은 이름 때문에 ReferenceError가 발생합니다 x, y그리고 z함수의 의미의 외부가 없습니다 f.

function f() {
    var x = 1
    let y = 1
    const z = 1
}
console.log(typeof x) // undefined (because var has function scope!)
console.log(typeof y) // undefined (because the body of the function is a block)
console.log(typeof z) // undefined (because the body of the function is a block)

다음은 의 가시성 이 블록에 의해 제한되지 않기 때문에 yz에 대해서는 ReferenceError를 발생 시키지 않습니다. 제어 구조의 시체를 정의 블록 좋아 , 와 유사하게 동작합니다.xxifforwhile

{
    var x = 1
    let y = 1
    const z = 1
}
console.log(x) // 1
console.log(typeof y) // undefined because `y` has block scope
console.log(typeof z) // undefined because `z` has block scope

다음에서는 함수 범위가 x있으므로 루프 외부에서 볼 수 있습니다 var.

for(var x = 0; x < 5; ++x) {}
console.log(x) // 5 (note this is outside the loop!)

...이 동작으로 인해 var루프에서 사용하여 선언 된 변수를 닫을 때주의해야합니다 . x여기에 선언 된 변수 인스턴스는 하나 뿐이며 논리적으로 루프 외부에 있습니다.

다음은 5을 다섯 번 인쇄 한 다음 루프 외부 5에 대해 여섯 번째 로 인쇄 console.log합니다.

for(var x = 0; x < 5; ++x) {
    setTimeout(() => console.log(x)) // closes over the `x` which is logically positioned at the top of the enclosing scope, above the loop
}
console.log(x) // note: visible outside the loop

다음 은 블록 범위 undefined이므로 인쇄 x됩니다. 콜백은 하나씩 비동기 적으로 실행됩니다. 새로운 행동 let각 익명 함수라는 이름의 다른 변수에 대해 닫혀 있음을 변수 수단 x(이 함께 할 것이다 달리 var) 및 정수 그래서 0를 통해 4인쇄 :

for(let x = 0; x < 5; ++x) {
    setTimeout(() => console.log(x)) // `let` declarations are re-declared on a per-iteration basis, so the closures capture different variables
}
console.log(typeof x) // undefined

다음은 블록 ReferenceError의 가시성이 x제한되지 않기 때문에를 던지지 않습니다. 그러나, 명령문 undefined때문에 변수가 초기화되지 않았기 때문에 인쇄 if됩니다.

if(false) {
    var x = 1
}
console.log(x) // here, `x` has been declared, but not initialised

for사용하여 루프 의 맨 위에 선언 된 변수는 루프 let의 본문으로 범위가 지정됩니다.

for(let x = 0; x < 10; ++x) {} 
console.log(typeof x) // undefined, because `x` is block-scoped

ReferenceError가시성은 x블록에 의해 제한 되기 때문에 다음이 발생 합니다.

if(false) {
    let x = 1
}
console.log(typeof x) // undefined, because `x` is block-scoped

변수로 선언 var, let또는 const모든 모듈에 범위가 있습니다 :

// module1.js

var x = 0
export function f() {}

//module2.js

import f from 'module1.js'

console.log(x) // throws ReferenceError

var전역 컨텍스트 내에서 사용하여 선언 된 변수가 전역 개체에 속성으로 추가되므로 다음은 전역 개체에 속성을 선언 합니다.

var x = 1
console.log(window.hasOwnProperty('x')) // true

letconst글로벌 맥락에서 전역 객체에 속성을 추가 할 수 있지만 여전히 글로벌 범위가 없습니다 :

let x = 1
console.log(window.hasOwnProperty('x')) // false

함수 매개 변수는 함수 본문에서 선언 된 것으로 간주 될 수 있습니다.

function f(x) {}
console.log(typeof x) // undefined, because `x` is scoped to the function

캐치 블록 매개 변수는 캐치 블록 본체에 적용됩니다.

try {} catch(e) {}
console.log(typeof e) // undefined, because `e` is scoped to the catch block

명명 된 함수 표현식은 표현식 자체에만 적용됩니다.

(function foo() { console.log(foo) })()
console.log(typeof foo) // undefined, because `foo` is scoped to its own expression

엄격하지 않은 모드에서는 전역 개체에 대해 암시 적으로 정의 된 속성의 범위가 전역 적으로 지정됩니다. 엄격 모드에서는 오류가 발생합니다.

x = 1 // implicitly defined property on the global object (no "var"!)

console.log(x) // 1
console.log(window.hasOwnProperty('x')) // true

엄격하지 않은 모드에서 함수 선언에는 함수 범위가 있습니다. 엄격 모드에서는 블록 범위가 있습니다.

'use strict'
{
    function foo() {}
}
console.log(typeof foo) // undefined, because `foo` is block-scoped

후드 아래에서 작동하는 방법

범위는 식별자가 유효한 코드 의 어휘 영역으로 정의됩니다 .

JavaScript에서 모든 function-object에는 숨겨진 컨텍스트 가 있으며 실행 컨텍스트 (스택 프레임) [[Environment]]어휘 환경 에 대한 참조 입니다.

함수를 호출하면 숨겨진 [[Call]]메소드가 호출됩니다. 이 메소드는 새 실행 컨텍스트를 작성하고 새 실행 컨텍스트와 함수 오브젝트의 어휘 환경 사이에 링크를 설정합니다. [[Environment]]함수 객체 의 값을 새 실행 컨텍스트의 어휘 환경에 있는 외부 참조 필드에 복사하여이를 수행합니다.

새로운 실행 컨텍스트와 함수 객체의 어휘 환경 사이의이 링크를 클로저 라고합니다 .

따라서 JavaScript에서 범위는 외부 참조에 의해 "체인"으로 함께 연결된 어휘 환경을 통해 구현됩니다. 이 어휘 환경 체인을 스코프 체인이라고하며, 식별자 확인 은 일치하는 식별자를 찾기 위해 체인검색하여 발생합니다 .

자세한 내용을 알아보십시오 .


280
포괄적이지는 않지만 현대 자바 스크립트를 효과적으로 읽는 데 필요한 자바 스크립트 범위 트릭입니다.
Triptych

148
높은 등급의 답변, 이유가 확실하지 않습니다. 적절한 설명이없는 예제 일뿐이며 프로토 타입 상속 (예 : 속성 확인)과 범위 체인 (예 : 가변 해상도)을 혼동하는 것처럼 보입니다. 범위 및 속성 확인에 대한 포괄적이고 정확한 설명은 comp.lang.javascript FAQ 노트에 있습니다.
RobG

109
@RobG 그것은 광범위한 프로그래머들에게 유용하고 이해하기 쉽기 때문에 높은 평가를받습니다. 귀하가 게시 한 링크는 일부 전문가에게는 유용하지만 오늘날 Javascript를 작성하는 대부분의 사람들에게는 이해가되지 않습니다. 답을 편집하여 명명법 문제를 자유롭게 해결하십시오.
Triptych

7
@ triptych— 주요 문제가 아닌 사소한 문제를 해결하기 위해 답변 만 편집합니다. "scope"를 "property"로 변경하면 오류가 수정되지만 상속과 범위가 명확하게 구분되지 않는 문제는 해결되지 않습니다.
RobG

24
외부 범위에서 변수를 정의한 다음 if 문을 사용 하면 분기에 도달하지 않더라도 동일한 이름으로 함수 내에 변수를 정의 할 수 있습니다 . 예 -jsfiddle.net/3CxVm
Chris S

233

Javascript는 범위 체인을 사용하여 지정된 함수의 범위를 설정합니다. 일반적으로 하나의 전역 범위가 있으며 정의 된 각 함수에는 자체 중첩 범위가 있습니다. 다른 함수 내에 정의 된 모든 함수에는 외부 함수에 연결된 로컬 범위가 있습니다. 항상 범위를 정의하는 소스의 위치입니다.

스코프 체인의 요소는 기본적으로 상위 범위에 대한 포인터가있는 맵입니다.

변수를 해결할 때 javascript는 가장 안쪽 범위에서 시작하여 바깥쪽으로 검색합니다.


1
스코프 체인은 [memory] Closures ...의 또 다른 용어로, 여기에서 읽고 자바 스크립트를 배우려는 사람들을위한 것입니다.
새로운 Alexandria

108

전역 적으로 선언 된 변수에는 전역 범위가 있습니다. 함수 내에서 선언 된 변수는 해당 함수로 범위가 지정되고 동일한 이름의 전역 변수를 음영 처리합니다.

(나는 확실히 실제 자바 스크립트 프로그래머는 다른 답변에서 지적 할 수있을 것으로 많은 미묘한이있다하고 있습니다. 특히 내가 건너 온에서 이 페이지 정확히 무엇에 대해 this언제든지 의미합니다. 희망은 이 더 소개 링크가 당신이 생각 시작할 수 있도록 충분하다 .)


7
이 질문에 대답하기 시작하는 것이 두렵습니다. 실제 자바 스크립트 프로그래머 인 저는 답변이 얼마나 빨리 벗어날 수 있는지 알고 있습니다. 좋은 기사.
Triptych

10
@Triptych : 손을 떼는 것에 대해 당신이 의미하는 바를 알고 있지만 어쨌든 대답을 추가 하십시오 . 내가 실제 경험을 가진 사람에 의해 쓰여진 답변이 있습니다 ... 단지 검색의 몇 일에서 위의 내용을 가지고 바인딩 더 좋을 수 있습니다. 그래도 분명히 틀린 내 대답을 수정하십시오!
Jon Skeet

4
어떻게 든 Jon Skeet은 Stack Overflow에서 가장 인기있는 답변을 담당합니다.
삼부작

75

구식 JavaScript

일반적으로 JavaScript는 실제로 두 가지 유형의 범위 만 있습니다.

  1. 글로벌 범위 : 변수는 응용 프로그램 시작부터 응용 프로그램 전체에 알려져 있습니다 (*)
  2. 기능 범위 : 변수는 함수 의 시작부터 선언 된 함수에서 알려져 있습니다 (*)

차이점을 설명하는 다른 많은 답변이 이미 있기 때문에 이에 대해 자세히 설명하지 않습니다.


현대 JavaScript

가장 최근의 자바 스크립트 사양은 이제 세 번째 범위를 허용 :

  1. 블록 범위 : 식별자는 자신이 선언 한 범위의 상단에서 "알려져" 있지만 선언이 끝날 때까지 식별자를 할당하거나 역 참조 (읽기) 할 수 없습니다. 이 기간을 "임시 데드 존"이라고합니다.

블록 범위 변수를 작성하는 방법

전통적으로 다음과 같이 변수를 만듭니다.

var myVariable = "Some text";

블록 범위 변수는 다음과 같이 생성됩니다.

let myVariable = "Some text";

기능 범위와 블록 범위의 차이점은 무엇입니까?

기능 범위와 블록 범위의 차이점을 이해하려면 다음 코드를 고려하십시오.

// i IS NOT known here
// j IS NOT known here
// k IS known here, but undefined
// l IS NOT known here

function loop(arr) {
    // i IS known here, but undefined
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( var i = 0; i < arr.length; i++ ) {
        // i IS known here, and has a value
        // j IS NOT known here
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    };

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( let j = 0; j < arr.length; j++ ) {
        // i IS known here, and has a value
        // j IS known here, and has a value
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    };

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here
}

loop([1,2,3,4]);

for( var k = 0; k < arr.length; k++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS NOT known here
};

for( let l = 0; l < arr.length; l++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS known here, and has a value
};

loop([1,2,3,4]);

// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here

여기에서 변수 j는 첫 번째 for 루프에서만 알려져 있지만 이전과 이후에는 알려지지 않았습니다. 그러나 우리의 변수 i는 전체 기능에 알려져 있습니다.

또한 블록 범위 변수는 게양되지 않았기 때문에 선언되기 전에 알 수 없습니다. 또한 동일한 블록 내에서 동일한 블록 범위 변수를 다시 선언 할 수 없습니다. 이렇게하면 블록 범위 변수가 전역 또는 기능 범위 변수보다 오류가 덜 발생합니다.이 변수는 게양되어 여러 선언의 경우 오류가 발생하지 않습니다.


오늘날 블록 범위 변수를 사용하는 것이 안전합니까?

오늘날 사용하기에 안전한지 여부는 환경에 따라 다릅니다.

  • 서버 측 JavaScript 코드 ( Node.js )를 let작성 하는 경우 명령문을 안전하게 사용할 수 있습니다 .

  • 클라이언트 측 JavaScript 코드를 작성하고 Traceur 또는 babel-standalone 과 같은 브라우저 기반 변환기를 사용하는 경우이 let명령문을 안전하게 사용할 수 있지만 코드는 성능 측면에서 최적 일 수 있습니다.

  • 클라이언트 측 JavaScript 코드를 작성하고 traceur 쉘 스크립트 또는 Babel 과 같은 노드 기반 변환기를 사용하는 경우 let명령문을 안전하게 사용할 수 있습니다 . 그리고 브라우저는 변환 된 코드에 대해서만 알기 때문에 성능 단점이 제한되어야합니다.

  • 클라이언트 측 JavaScript 코드를 작성 중이고 트랜스 파일러를 사용하지 않는 경우 브라우저 지원을 고려해야합니다.

    이들은 전혀 지원하지 않는 일부 브라우저입니다 let.

    • 인터넷 익스플로러 10 이하
    • Firefox 43 이하
    • 사파리 9 이하
    • 안드로이드 브라우저 4 이하
    • 오페라 27 이하
    • Chome 40 이하
    • 모든 버전의 Opera Mini & Blackberry Browser

여기에 이미지 설명을 입력하십시오


브라우저 지원을 추적하는 방법

let이 답변을 읽을 당시의 진술을 지원하는 브라우저에 대한 최신 개요는 Can I Use페이지를 참조 하십시오 .


(*) JavaScript 변수가 들어 있기 때문에 전역 및 기능적으로 범위가 지정된 변수를 선언하기 전에 초기화하고 사용할 수 있습니다 . 이것은 선언이 항상 범위의 맨 위에 있다는 것을 의미합니다.


2
게양으로 인해 변수가 선언되었으므로 "알 수 없음"이 잘못되었습니다.
Oriol

위의 예는 잘못된 것으로, 변수 'i'및 'j'는 블록 외부에 알려지지 않았습니다. 'Let'변수는 블록 외부가 아닌 특정 블록에서만 범위를 갖습니다. 다른 장점도 있지만 변수를 다시 선언 할 수 없으며 어휘 범위를 유지합니다.
zakir

1
도움이되었습니다. 감사합니다! "Modern JavaScript"와 "Old school JavaScript"의 의미에 대해 구체적으로 설명하면 더 도움이 될 것입니다. 나는 이것들이 각각 ECMAScript 6 / ES6 / ECMAScript 2015 및 이전 버전에 해당한다고 생각합니까?
Jon Schneider

1
@ JonSchneider : 맞아요! "구식 JavaScript"라고 말하면 ECMAScript 5에 대해 이야기하고 있고 "현대 JavaScript"에 대해서는 ECMAScript 6 (일명 ECMAScript 2015)에 관한 것입니다. 그러나 대부분의 사람들은 (1) 블록 범위와 기능 범위의 차이점, (2) 브라우저가 블록 범위를 지원하는 브라우저 및 (3) 알고 싶어하기 때문에 여기서 자세히 설명하는 것이 중요하다고 생각하지 않았습니다. 현재 작업중인 프로젝트에 대해 블록 범위를 사용하는 것이 안전한지 여부 그래서 나는 그 문제를 해결하는데 집중했다.
John Slegers

1
@JonSchneider : (계속) 그럼에도 불구하고 방금 지난 몇 년 동안 JavaScript에 추가 된 기능에 대해 더 알고 싶은 사람들을 위해 ES6 / ES2015의 Smashing Magazine 기사에 대한 링크를 추가했습니다 ... "modern JavaScript"의 의미가 궁금 할 것입니다.
John Slegers

39

예를 들면 다음과 같습니다.

<script>

var globalVariable = 7; //==window.globalVariable

function aGlobal( param ) { //==window.aGlobal(); 
                            //param is only accessible in this function
  var scopedToFunction = {
    //can't be accessed outside of this function

    nested : 3 //accessible by: scopedToFunction.nested
  };

  anotherGlobal = {
    //global because there's no `var`
  }; 

}

</script>

클로저를 조사하고 클로저를 사용하여 비공개 회원 을 만드는 방법을 조사해야합니다 .



26

"Javascript 1.7"(Mozilla의 Javascript 확장)에서 다음 과 같이 letstatement -scope 변수를 선언 할 수 있습니다 .

 var a = 4;
 let (a = 3) {
   alert(a); // 3
 }
 alert(a);   // 4

2
예, 그러나 사용하는 것이 안전합니까? 내 코드가 WebKit에서 실행될 경우 실제로이 구현을 선택해야합니까?
IgorGanapolsky

10
@Python : 아니요, WebKit은 지원하지 않습니다 let.
kennytm

모든 클라이언트가 회사 내부 시스템과 같은 Mozilla 브라우저를 사용한다는 것을 알고 있다면 이것이 유일하게 유효한 것으로 생각됩니다.
GazB

또는 XUL 프레임 워크를 사용하여 프로그래밍하는 경우 css, xml 및 javascript를 사용하여 빌드하는 Mozilla의 인터페이스 프레임 워크입니다.
Gerard ONeill

1
@ GazB조차도 끔찍한 생각입니다! 그래서 오늘 당신은 당신의 클라이언트가 Mozilla를 사용하고 있다는 것을 알고 있으며 이제는 다른 것을 사용하고 있다는 새로운 메모가 나옵니다. IE는 이유는 우리의 지불 시스템은 ... 당신은 그것을 때문에 평면 못해 워크 아웃 IE8 결코 IE9 또는 IE10 또는 파이어 폭스 나 크롬을 사용합니다 ... 짜증
buzzsawddog

25

Brendan Eich 가 처음 디자인했을 때 JavaScript 범위 지정 아이디어 는 HyperCard 스크립팅 언어 인 HyperTalk 에서 나왔습니다 .

이 언어에서는 디스플레이가 인덱스 카드 스택과 유사하게 수행되었습니다. 배경이라고하는 마스터 카드가있었습니다. 투명하고 맨 아래 카드로 볼 수 있습니다. 이 기본 카드의 모든 내용은 그 위에 놓인 카드와 공유되었습니다. 상단에 배치 된 각 카드에는 이전 카드보다 우선하는 고유 한 내용이 있지만 원하는 경우 여전히 이전 카드에 액세스 할 수있었습니다.

이것이 바로 JavaScript 범위 시스템이 설계된 방식입니다. 이름이 다릅니다. JavaScript의 카드는 Execution Contexts ECMA라고 합니다. 이러한 맥락 각각에는 세 가지 주요 부분이 있습니다. 가변 환경, 어휘 환경 및이 바인딩 카드 참조로 돌아가서 어휘 환경에는 이전 카드의 모든 내용이 스택 아래에 포함됩니다. 현재 컨텍스트는 스택 맨 위에 있으며 여기에 선언 된 모든 컨텐츠는 가변 환경에 저장됩니다. 이름 충돌의 경우 변수 환경이 우선합니다.

이 바인딩은 포함하는 객체를 가리 킵니다. 포함 개체가 생성 된 선언 된 함수 window나 생성자 함수 와 같이 포함 개체를 변경하지 않고 범위 나 실행 컨텍스트가 변경되는 경우가 있습니다 .

이러한 실행 컨텍스트는 제어가 전송 될 때마다 작성됩니다. 코드 실행이 시작되면 제어가 전송되며 이는 주로 함수 실행에서 수행됩니다.

이것이 기술적 인 설명입니다. 실제로는 JavaScript에서이를 기억하는 것이 중요합니다

  • 범위는 기술적으로 "실행 컨텍스트"입니다.
  • 컨텍스트는 변수가 저장된 환경의 스택을 형성합니다
  • 스택의 상단이 우선합니다 (하단은 전역 컨텍스트 임)
  • 각 함수는 실행 컨텍스트를 생성합니다 (그러나 항상이 바인딩이 새로운 것은 아닙니다)

이 페이지의 이전 예제 중 하나 (5. "Closure")에이를 적용하면 실행 컨텍스트 스택을 따를 수 있습니다. 이 예에서는 스택에 세 가지 컨텍스트가 있습니다. 외부 컨텍스트, var six에 의해 호출 된 즉시 호출 된 함수의 컨텍스트 및 var six의 즉시 호출 된 함수 내에서 리턴 된 함수의 컨텍스트에 의해 정의됩니다.

i ) 외부 상황. 변수 환경 a = 1
ii ) IIFE 컨텍스트, 어휘 환경 a = 1이지만 스택 환경에서 우선 순위가 높은 a = 6 변수 환경
iii ) 리턴 된 함수 컨텍스트, 어휘 a = 6의 환경이며 호출 될 때 경고에서 참조되는 값입니다.

여기에 이미지 설명을 입력하십시오


17

1) 전역 범위, 기능 범위 및 with 및 catch 범위가 있습니다. 변수에 대해 일반적으로 '블록'레벨 범위는 없습니다. with 및 catch 문은 블록에 이름을 추가합니다.

2) 범위는 전역 범위까지 모든 기능에 의해 중첩됩니다.

3) 프로토 타입 체인을 통해 속성이 해결됩니다. with 문은 객체 속성 이름을 with 블록으로 정의 된 어휘 범위로 가져옵니다.

편집 : ECMAAScript 6 (Harmony)은 let을 지원하도록 지정되어 있으며 크롬은 'harmony'플래그를 허용하므로 아마도 지원합니다.

블록 레벨 범위 지정을 지원하지만 키워드를 사용하여이를 수행해야합니다.

편집 : Benjamin의 의견에 with 및 catch 문을 지적한 결과 게시물을 편집하고 더 추가했습니다. 모두가 함께하고 catch 문은 각각의 블록으로 변수를 소개하고 그 입니다 블록 범위. 이러한 변수는 전달 된 객체의 속성에 별칭이 지정됩니다.

 //chrome (v8)

 var a = { 'test1':'test1val' }
 test1   // error not defined
 with (a) { var test1 = 'replaced' }
 test1   // undefined
 a       // a.test1 = 'replaced'

편집 : 예를 명확하게 :

test1의 범위는 with 블록이지만 a.test1의 별칭입니다. 'Var test1'은 어휘 컨텍스트 (함수 또는 전역)에 새로운 변수 test1을 작성합니다.

이케! 변수가 이미 함수에 정의되어 있다면 var는 noop 인 것처럼 'with'를 사용하는 것에주의하십시오. 객체에서 가져온 이름과 관련하여 noop이기도합니다! 이미 정의 된 이름에 약간의 머리글이 있으면 훨씬 더 안전합니다. 이 때문에 개인적으로는 절대 사용하지 않습니다.


여기에 약간의 실수가 있습니다. 하나의 JavaScript에는 블록 범위 지정 형식이 있기 때문입니다.
Benjamin Gruenbaum

벤자민 (Benjamin)-나의 귀 (눈)가 열려 있습니다. 위의 진술은 제가 자바 스크립트 범위를 어떻게 다루 었는지에 대한 것입니다. with 문 (객체 범위 지정의 형태)이나 Mozilla의 특별한 'let'구문을 언급하지 않기를 바랍니다.
Gerard ONeill

음, with입니다 블록 범위 지정의 형태는하지만 catch절은 훨씬 더 일반적인 형태 (재미있는 사실, V8의 구현입니다 catchA를 with) - 자바 스크립트 자체 (즉, 기능, 글로벌, 시도 / 잡기에 거의 블록 범위 지정의 유일한 형태이다 호스트 환경과 브라우저의 인라인 이벤트 및 NodeJS의 vm 모듈과 같은 범위 지정 개념이 다릅니다.
Benjamin Gruenbaum

벤자민-내가 볼 수있는 것에서 객체는 현재 범위 (및 속성)로 객체를 소개하지만 각 블록이 끝나면 변수가 재설정됩니다. 그러나 예를 들어, catch에 도입 된 새 변수는 둘러싸는 함수 / 메소드의 범위를 갖습니다.
Gerard ONeill

2
어떤 정확히 블록 범위 지정 수단 :
벤자민 Gruenbaum

9

JavaScript를 처음 접하는 많은 사람들은 기본적으로 언어에서 상속이 가능하며 함수 범위가 유일한 범위라는 것을 이해하는 데 어려움을 겪었습니다. 작년 말에 JSPretty라고 썼던 미용사에 대한 확장을 제공했습니다. 피처 색상은 코드에서 기능 범위이며 항상 해당 범위에서 선언 된 모든 변수에 색상을 연결합니다. 한 범위의 색상을 가진 변수가 다른 범위에서 사용될 때 클로저가 시각적으로 표시됩니다.

다음에서 기능을 사용해보십시오.

다음에서 데모를보십시오 :

다음에서 코드를보십시오.

현재이 기능은 깊이가 16 인 중첩 함수를 지원하지만 전역 변수에 색상을 지정하지는 않습니다.


1
Firefox 26에서는 작동하지 않습니다. 코드를 붙여 넣거나 파일을로드하고 실행을 클릭해도 아무 변화가 없습니다.
mplwork 2019

범위와 상속은 두 가지 차이점입니다.
벤 애스턴

9

JavaScript에는 두 가지 유형의 범위 만 있습니다.

  1. 전역 범위 : 전역은 창 수준 범위 에 지나지 않습니다. 여기서 응용 프로그램 전체에 변수가 있습니다.
  2. 기능 범위 : var키워드를 사용 하여 함수 내에 선언 된 변수 에는 기능 범위가 있습니다.

함수가 호출 될 때마다 변수 범위 개체가 만들어지고 범위 체인에 포함되며 그 뒤에 JavaScript의 변수가옵니다.

        a = "global";
         function outer(){ 
              b = "local";
              console.log(a+b); //"globallocal"
         }
outer();

스코프 체인->

  1. 창 수준- aouter기능은 범위 체인에서 최상위 수준에 있습니다.
  2. 외부 함수가 새로운 함수 variable scope object(및 스코프 체인에 포함)에 변수가 추가 된 b경우.

이제 변수가 a필요할 때 가장 가까운 변수 범위를 검색하고 변수가 없으면 변수 범위 체인의 다음 객체로 이동합니다.이 경우 창 수준입니다.


1
이것이 왜 대답이 아닌지 잘 모르겠습니다. 실제로 기능 범위 (ECMA6 이전에는 "로컬 범위"가 없었 음)와 전역 바인딩이 있습니다.
texasbruce

9

다른 답변에 추가하기 위해 scope는 선언 된 모든 식별자 (변수)의 조회 목록이며 현재 실행중인 코드에 액세스 할 수있는 방법에 대한 엄격한 규칙을 시행합니다. 이 조회는 LHS (왼쪽) 참조 인 변수에 할당하기위한 것이거나 RHS (오른쪽) 참조 인 값을 검색하기위한 것일 수 있습니다. 이러한 조회는 JavaScript 엔진이 코드를 컴파일하고 실행할 때 내부적으로 수행하는 작업입니다.

이 관점에서, 그림이 Kyle Simpson의 Scopes and Closures ebook에서 찾은 데 도움이 될 것이라고 생각합니다.

영상

그의 전자 책에서 인용 :

건물은 프로그램의 중첩 범위 규칙 세트를 나타냅니다. 건물의 1 층은 어디에 있든지 현재 실행중인 범위를 나타냅니다. 건물의 최상위 수준은 글로벌 범위입니다. 현재 층을 살펴보고 LHS 및 RHS 참조를 해결하고, 찾을 수없는 경우 엘리베이터를 다음 층으로 가져 가서 다음 층을 찾은 후 다음 등을 수행합니다. 최상층에 도달하면 (전세계 범위) 원하는 것을 찾거나 찾지 않습니다. 그러나 당신은 관계없이 멈춰야합니다.

주목할만한 한 가지 사항은 "첫 번째 일치 항목을 찾으면 스코프 조회가 중지됩니다"입니다.

"범위 수준"에 대한이 개념은 중첩 함수에서 조회되는 경우 "이"가 새로 작성된 범위로 변경 될 수있는 이유를 설명합니다. 여기에 모든 세부 사항으로 연결되는 링크가 있습니다 .Javascript 범위에 대해 알고 싶은 모든 것


8

코드를 실행하십시오. 이것이 범위 지정에 대한 아이디어를 줄 수 있기를 바랍니다.

Name = 'global data';
document.Name = 'current document data';
(function(window,document){
var Name = 'local data';
var myObj = {
    Name: 'object data',
    f: function(){
        alert(this.Name);
    }
};

myObj.newFun = function(){
    alert(this.Name);
}

function testFun(){
    alert("Window Scope : " + window.Name + 
          "\nLocal Scope : " + Name + 
          "\nObject Scope : " + this.Name + 
          "\nCurrent document Scope : " + document.Name
         );
}


testFun.call(myObj);
})(window,document);

8

글로벌 범위 :

글로벌 변수는 글로벌 스타와 정확히 같습니다 (Jackie Chan, Nelson Mandela). 응용 프로그램의 어느 부분에서나 액세스 할 수 있습니다 (값을 얻거나 설정). 글로벌 기능은 글로벌 이벤트 (새해, 크리스마스)와 같습니다. 애플리케이션의 어느 부분에서나 실행 (호출) 할 수 있습니다.

//global variable
var a = 2;

//global function
function b(){
   console.log(a);  //access global variable
}

지역 범위 :

당신이 미국에 있다면, 유명한 연예인 인 Kim Kardashian을 알게 될 것입니다. 그러나 미국 이외의 사람들은 그녀를 인식하지 못할 것입니다. 그녀는 자신의 영토에 묶인 지역 별입니다.

지역 변수는 지역 별과 같습니다. 범위 내에서만 액세스 할 수 있습니다 (값을 가져 오거나 설정). 로컬 함수는 로컬 이벤트와 유사합니다. 해당 범위 내에서만 (축하) 실행할 수 있습니다. 범위 밖에서 액세스하려는 경우 참조 오류가 발생합니다.

function b(){
   var d = 21; //local variable
   console.log(d);

   function dog(){  console.log(a); }
     dog(); //execute local function
}

 console.log(d); //ReferenceError: dddddd is not defined    

범위에 대한 자세한 내용은이 기사를 확인하십시오.


6

ALMOST에는 두 가지 유형의 JavaScript 범위 만 있습니다.

  • 각 var 선언의 범위는 가장 즉시 묶는 함수와 연관됩니다.
  • var 선언에 대한 엔 클로징 함수가 없으면 전역 범위입니다.

따라서 함수 이외의 블록은 새로운 범위를 만들지 않습니다. for 루프가 외부 범위 변수를 덮어 쓰는 이유를 설명합니다.

var i = 10, v = 10;
for (var i = 0; i < 5; i++) { var v = 5; }
console.log(i, v);
// output 5 5

대신 함수 사용하기 :

var i = 10, v = 10;
$.each([0, 1, 2, 3, 4], function(i) { var v = 5; });
console.log(i,v);
// output 10 10

첫 번째 예에서는 블록 범위가 없었으므로 처음 선언 된 변수를 덮어 썼습니다. 두 번째 예에서는 함수로 인해 새로운 범위가 있었으므로 처음 선언 된 변수는 SHADOWED이며 덮어 쓰지 않았습니다.

JavaScript 범위 지정과 관련하여 알아야 할 거의 모든 것이 있습니다.

따라서 JavaScript 범위 지정은 실제로 매우 간단하지만 항상 매우 간단하다는 것을 알 수 있습니다. 몇 가지 알아 두어야 할 사항 :

  • var 선언은 범위의 맨 위로 들어갑니다. 이것은 var 선언이 어디에서 발생하더라도 컴파일러 자체가 var 자체가 최상위에서 발생하는 것처럼
  • 동일한 범위 내의 여러 var 선언이 결합됩니다.

따라서이 코드 :

var i = 1;
function abc() {
  i = 2;
  var i = 3;
}
console.log(i);     // outputs 1

다음과 같습니다.

var i = 1;
function abc() {
  var i;     // var declaration moved to the top of the scope
  i = 2;
  i = 3;     // the assignment stays where it is
}
console.log(i);

이것은 직관적이지 않은 것처럼 보일 수도 있지만 명령형 언어 디자이너의 관점에서 의미가 있습니다.


5

현대 JS, ES6 +, ' const'및 ' let'

대부분의 다른 주요 언어와 마찬가지로 작성하는 모든 변수에 대해 블록 범위 지정을 사용해야합니다. var이다 쓸모 . 이를 통해 코드를보다 안전하고 유지 관리 할 수 ​​있습니다.

const95 %의 경우에 사용해야합니다 . 변수 참조 를 변경할 수 없도록 만듭니다 . 배열, 객체 및 DOM 노드 속성은 변경 될 수 있으며 변경 될 수 있습니다 const.

let재 할당 될 것으로 예상되는 모든 변수에 사용해야합니다. 여기에는 for 루프가 포함됩니다. 초기화 이상으로 값을 변경 한 경우을 사용하십시오 let.

블록 범위는 변수가 선언 된 괄호 내에서만 변수를 사용할 수 있음을 의미합니다. 이는 범위 내에서 생성 된 익명 함수를 포함하여 내부 범위로 확장됩니다.


3

이 호기심 많은 예를보십시오. 아래 예제에서 a가 0에서 초기화 된 숫자 인 경우 0과 1이 표시됩니다. a는 객체이고 javascript는 f1을 복사하지 않고 포인터로 전달합니다. 결과적으로 동일한 경고가 두 번 나타납니다.

var a = new Date();
function f1(b)
{
    b.setDate(b.getDate()+1);
    alert(b.getDate());
}
f1(a);
alert(a.getDate());

3

JS에는 기능 범위 만 있습니다. 범위를 차단하지 마십시오! 당신은 게양도 볼 수 있습니다.

var global_variable = "global_variable";
var hoisting_variable = "global_hoist";

// Global variables printed
console.log("global_scope: - global_variable: " + global_variable);
console.log("global_scope: - hoisting_variable: " + hoisting_variable);

if (true) {
    // The variable block will be global, on true condition.
    var block = "block";
}
console.log("global_scope: - block: " + block);

function local_function() {
    var local_variable = "local_variable";
    console.log("local_scope: - local_variable: " + local_variable);
    console.log("local_scope: - global_variable: " + global_variable);
    console.log("local_scope: - block: " + block);
    // The hoisting_variable is undefined at the moment.
    console.log("local_scope: - hoisting_variable: " + hoisting_variable);

    var hoisting_variable = "local_hoist";
    // The hoisting_variable is now set as a local one.
    console.log("local_scope: - hoisting_variable: " + hoisting_variable);
}

local_function();

// No variable in a separate function is visible into the global scope.
console.log("global_scope: - local_variable: " + local_variable);

(답변 게시 이후 오랜 시간) 블록 범위; developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
Bob

2

내 이해는 3 가지 범위가 있다는 것입니다 : 글로벌 범위, 전 세계적으로 사용 가능; 블록에 관계없이 전체 기능에 사용 가능한 로컬 범위; 그리고 블록 범위는 블록, 명령문 또는 블록이 사용 된 표현식에서만 사용 가능합니다. 전역 및 로컬 범위는 함수 내에서 또는 외부에서 키워드 'var'로 표시되며 블록 범위는 키워드 'let'으로 표시됩니다.

글로벌 및 로컬 범위 만 있다고 생각하는 사람들을 위해 Mozilla가 JS에서 블록 범위의 뉘앙스를 설명하는 전체 페이지를 갖는 이유를 설명하십시오.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let


2

프론트 엔드 코더가 자주 발생하는 매우 일반적인 문제는 HTML에서 인라인 이벤트 핸들러에 표시되는 범위입니다.

<button onclick="foo()"></button>

on*속성이 참조 할 수 있는 변수의 범위는 다음 중 하나 여야 합니다.

  • 전역 (작업 인라인 핸들러는 거의 항상 전역 변수를 참조합니다)
  • 문서의 속성 (예를 들어, querySelector독립형 변수는 document.querySelector; 희귀)
  • 핸들러가 부착 된 요소의 속성 (위와 같지만 드문 경우)

그렇지 않으면 핸들러가 호출 될 때 ReferenceError가 발생합니다. 예를 들어 인라인 핸들러가 or 안에 정의 된 함수를 참조하는 경우 인라인 핸들러는 전역 범위의 변수 만 참조 할 수 있고 함수는 전역이 아니므로 참조가 실패합니다.window.onload$(function() {

의 속성 document과 인라인 핸들러가 핸들러가 호출되기 때문에 또한 인라인 처리기 내부 독립 변수로 참조 될 수있는 부착 된 소자의 특성을 내부에 두개의 with블록 은 하나 document의 요소를 하나. 이러한 핸들러 내부 변수의 범위 체인은 매우 직관적 및 작동 이벤트 핸들러 것이다 아마도 글로벌하려고 한 기능을 요구 (글로벌 불필요한 오염 아마 피해야한다 ).

인라인 핸들러 내부의 스코프 체인은 너무 이상 하고 인라인 핸들러가 작동하려면 전역 오염이 필요하고 인라인 핸들러는 인수를 전달할 때 추악한 문자열 이스케이프가 필요하기 때문에 피하는 것이 더 쉽습니다. 대신 addEventListenerHTML 마크 업이 아닌 Javascript를 사용하여 이벤트 핸들러를 연결하십시오 .


다른 참고로 <script>최상위 수준에서 실행되는 일반 태그 와 달리 ES6 모듈 내부의 코드는 자체 개인 범위에서 실행됩니다. 일반 <script>태그 상단에 정의 된 변수 는 전역이므로 다음 <script>과 같이 다른 태그 에서 참조 할 수 있습니다 .

그러나 ES6 모듈의 최상위 수준은 전 세계 가 아닙니다 . ES6 모듈 상단에 선언 된 변수는 변수가 명시 적으로 export지정되거나 전역 객체의 속성에 할당되지 않은 경우 해당 모듈 내에서만 볼 수 있습니다 .

ES6 모듈의 최상위 레벨은 정상에서 최상위 레벨의 IIFE 내부와 유사합니다 <script>. 모듈은 전역 변수를 참조 할 수 있으며, 모듈이 명시 적으로 설계되지 않은 경우 모듈 내부의 어떤 것도 참조 할 수 없습니다.


1

JavaScript에는 두 가지 유형의 범위가 있습니다.

  • 지역 범위
  • 글로벌 범위

아래 함수에는 로컬 범위 변수가 carName있습니다. 그리고이 변수는 함수 외부에서 액세스 할 수 없습니다.

function myFunction() {
    var carName = "Volvo";
    alert(carName);
    // code here can use carName
}

아래 클래스에는 전역 범위 변수가 carName있습니다. 이 변수는 클래스의 어느 곳에서나 액세스 할 수 있습니다.

class {

    var carName = " Volvo";

    // code here can use carName

    function myFunction() {
        alert(carName);
        // code here can use carName 
    }
}

1

ES5 이전 :

Javascript의 변수는 초기에 ES6사전 기능 범위로 사용되었습니다. 어휘 범위라는 용어는 코드를 '보고'변수의 범위를 볼 수 있음을 의미합니다.

var키워드로 선언 된 모든 변수의 범위는 함수입니다. 그러나 다른 함수가 해당 함수 내에 선언되면 해당 함수는 외부 함수의 변수에 액세스 할 수 있습니다. 이것을 스코프 체인 이라고합니다 . 다음과 같은 방식으로 작동합니다.

  1. 함수가 변수 값을 확인할 때 먼저 자체 범위를 봅니다. 이것은 함수 본문입니다. 즉 중괄호 {} 사이의 모든 것입니다 ( 이 범위에있는 다른 함수 내의 변수는 제외 ).
  2. 함수 본문 내에서 변수를 찾을 수 없으면 체인으로 올라가 함수가 정의 된 함수에서 변수 범위를 확인합니다 . 이것은 어휘 범위의 의미입니다.이 함수가 정의 된 코드에서 볼 수 있으므로 코드를 살펴보면 범위 체인을 결정할 수 있습니다.

예:

// global scope
var foo = 'global';
var bar = 'global';
var foobar = 'global';

function outerFunc () {
 // outerFunc scope
 var foo = 'outerFunc';
 var foobar = 'outerFunc';
 innerFunc();
 
 function innerFunc(){
 // innerFunc scope
  var foo = 'innerFunc';
  console.log(foo);
  console.log(bar);
  console.log(foobar);
  }
}

outerFunc();

어떻게 우리가 변수를 로그인을 시도 할 때 발생하는 foo, bar그리고 foobar콘솔에 다음과 같다 :

  1. 우리는 foo를 콘솔에 기록하려고 시도합니다. foo는 함수 innerFunc자체 에서 찾을 수 있습니다 . 따라서 foo 값은 문자열로 확인됩니다 innerFunc.
  2. 우리는 콘솔에 bar를 로그하려고 시도하는데, 함수 innerFunc자체 안에서 bar를 찾을 수 없습니다 . 따라서 스코프 체인올라 가야합니다 . 먼저 함수 innerFunc가 정의 된 외부 함수를 살펴 봅니다 . 이것은 기능 outerFunc입니다. 범위 내 outerFunc에서 문자열 'outerFunc'를 보유하는 변수 막대를 찾을 수 있습니다.
  3. innerFunc에서 foobar를 찾을 수 없습니다. . 따라서 스코프 체인 을 innerFunc 스코프 까지 올라 가야합니다 . 또한 여기서 찾을 수 없습니다. 우리는 또 다른 차원을 글로벌 범위 (즉, 가장 바깥 쪽 범위)로 올립니다 . 문자열 'global'을 보유한 변수 foobar가 있습니다. 스코프 체인을 올라간 후 변수를 찾지 못하면 JS 엔진은 referenceError를 발생 시킵니다.

ES6 (ES 2015) 이상 :

어휘 범위와 범위 체인의 동일한 개념이 여전히 적용됩니다 ES6. 그러나 변수를 선언하는 새로운 방법이 도입되었습니다. 다음이 있습니다 :

  • let: 블록 범위 변수를 작성합니다
  • const: 초기화해야하고 재 할당 할 수없는 블록 범위 변수를 작성합니다.

가장 큰 차이점 varlet/ constvar함수 인 반면, 범위 let/ const블록 범위이다. 다음은이를 설명하는 예입니다.

let letVar = 'global';
var varVar = 'global';

function foo () {
  
  if (true) {
    // this variable declared with let is scoped to the if block, block scoped
    let letVar = 5;
    // this variable declared with let is scoped to the function block, function scoped
    var varVar = 10;
  }
  
  console.log(letVar);
  console.log(varVar);
}


foo();

위의 예에서 letVar는로 선언 된 변수 let가 블록 범위 이기 때문에 전역 값을 기록합니다 . 그것들은 각각의 블록 외부에 존재하지 않으므로 변수는 if 블록 외부에 액세스 할 수 없습니다.


0

EcmaScript5에는 주로 로컬 범위전역 범위의 두 가지 범위가 있지만 EcmaScript6에는 주로 로컬 범위, 전역 범위 및 블록 범위 라는 새로운 범위의 세 가지 범위가 있습니다. .

블록 범위의 예는 다음과 같습니다.

for ( let i = 0; i < 10; i++)
{
 statement1...
statement2...// inside this scope we can access the value of i, if we want to access the value of i outside for loop it will give undefined.
}

0

ECMAScript 6에는 let 및 const 키워드가 도입되었습니다. 이 키워드는 var 키워드 대신 사용할 수 있습니다. var 키워드와 달리 let 및 const 키워드는 블록 명령문 내에서 로컬 범위 선언을 지원합니다.

var x = 10
let y = 10
const z = 10
{
  x = 20
  let y = 20
  const z = 20
  {
    x = 30
    // x is in the global scope because of the 'var' keyword
    let y = 30
    // y is in the local scope because of the 'let' keyword
    const z = 30
    // z is in the local scope because of the 'const' keyword
    console.log(x) // 30
    console.log(y) // 30
    console.log(z) // 30
  }
  console.log(x) // 30
  console.log(y) // 20
  console.log(z) // 20
}

console.log(x) // 30
console.log(y) // 10
console.log(z) // 10

0

나는 받아 들인 대답을 정말로 좋아하지만 이것을 추가하고 싶다 :

Scope는 선언 된 모든 식별자 (변수)의 조회 목록을 수집하고 유지 관리하며 현재 실행중인 코드에 액세스 할 수있는 방법에 대한 엄격한 규칙을 적용합니다.

범위는 식별자 이름으로 변수를 조회하기위한 규칙 세트입니다.

  • 즉각적인 범위에서 변수를 찾을 수없는 경우 엔진은 다음 외부 포함 범위를 참조하여 발견 될 때까지 또는 가장 바깥 쪽 (일명 글로벌) 범위에 도달 할 때까지 계속합니다.
  • 변수 (식별자)를 찾을 수있는 위치와 방법을 결정하는 규칙 집합입니다. 이 조회는 LHS (왼쪽) 참조 인 변수에 할당하기위한 것이거나 RHS (오른쪽) 참조 인 값을 검색하기위한 것일 수 있습니다. .
  • LHS 참조는 할당 작업의 결과입니다. 범위 관련 할당은 = 연산자를 사용하거나 함수 매개 변수에 인수를 전달하여 발생할 수 있습니다.
  • JavaScript 엔진은 코드를 실행하기 전에 먼저 코드를 컴파일하므로 var a = 2; 두 개의 별도 단계로 진행됩니다. 먼저 var a를 해당 범위에서 선언하십시오. 이것은 코드 실행 전에 처음에 수행됩니다. 2 일. 나중에 a = 2로 변수 (LHS 참조)를 찾아서 찾은 경우 할당합니다.
  • LHS 및 RHS 참조 조회는 모두 현재 실행중인 범위에서 시작하며, 필요한 경우 (즉, 원하는 것을 찾지 못하는 경우) 중첩 된 범위에서 하나의 범위 (플로어)로 작동합니다. )를 사용하여 전역 (상층)에 도착하여 정지하거나 찾을 때까지 식별자를 찾습니다. 충족되지 않은 RHS 참조는 ReferenceError가 발생합니다. 충족되지 않은 LHS 참조는 자동으로 암시 적으로 해당 이름의 전역을 생성하거나 (엄격한 모드가 아닌 경우) ReferenceError (엄격한 모드 인 경우)를 초래합니다.
  • scope는 각각 식별자 또는 변수가 선언되는 컨테이너 또는 버킷 역할을하는 일련의 "버블 (bubbles)"로 구성됩니다. 이 거품은 서로 깔끔하게 중첩되며이 중첩은 제작 시점에 정의됩니다.

-3

JavaScript에는 두 가지 유형의 범위가 있습니다.

  1. 글로벌 스코프 : 글로벌 스코프에 공지 된 변수는 프로그램의 어느 곳에서나 매우 부드럽게 사용될 수 있습니다. 예를 들면 다음과 같습니다.

    var carName = " BMW";
    
    // code here can use carName
    
    function myFunction() {
         // code here can use carName 
    }
  2. 기능 범위 또는 로컬 범위 :이 범위에서 선언 된 변수는 자체 기능에서만 사용할 수 있습니다. 예를 들면 다음과 같습니다.

    // code here can not use carName
    function myFunction() {
       var carName = "BMW";
       // code here can use carName
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.