본문 바로가기
카테고리 없음

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

by RWriter 2023. 1. 22.
반응형

질문 제목:

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

질문 내용:

javascript에서 변수의 범위는 무엇입니까? 함수 외부와 달리 내부에 동일한 범위가 있습니까? 아니면 중요합니까? 또한 전역적으로 정의된 변수는 어디에 저장됩니까?

해결 답변:

TLDR

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

  1. 글로벌 - 모든 것이 볼 수 있음
  2. 기능 - 기능(및 해당 하위 기능 및 블록) 내에서 볼 수 있습니다.
  3. 블록 - 블록(및 해당 하위 블록) 내에서 볼 수 있습니다.
  4. 모듈 - 모듈 내에서 볼 수 있음

전역 및 모듈 범위의 특수한 경우를 제외하고 변수는

var

(함수 범위),

let

(블록 범위) 및

const

(블록 범위)를 사용하여 선언됩니다. 대부분의 다른 형식의 식별자 선언에는 엄격 모드에서 블록 범위가 있습니다.

개요

범위는 식별자가 유효한 코드베이스의 영역입니다.어휘 환경은 식별자 이름과 이와 관련된 값 간의 매핑입니다.범위는 상위 실행 컨텍스트의 어휘 환경에 해당하는 중첩의 각 수준과 함께 어휘 환경의 연결된 중첩으로 구성됩니다.이러한 연결된 어휘 환경은 범위 "체인"을 형성합니다. 식별자 확인은 이 체인을 따라 일치하는 식별자를 검색하는 프로세스입니다.식별자 확인은 한 방향, 즉 바깥쪽으로만 발생합니다. 이런 식으로 외부 어휘 환경은 내부 어휘 환경을 "볼" 수 없습니다.JavaScript 에서 식별자 의

범위

를 결정하는 세 가지 관련 요소가 있습니다 .

  1. 식별자 선언 방법
  2. 식별자가 선언된 위치
  3. 엄격 모드 인지 엄격 모드 인지 여부

식별자를 선언할 수 있는 몇 가지 방법은 다음과 같습니다.

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

일부 위치 식별자는 다음과 같이 선언할 수 있습니다.

  1. 글로벌 컨텍스트
  2. 함수 본문
  3. 일반 블록
  4. 제어 구조의 맨 위(예: 루프, if, while 등)
  5. 제어 구조 본체
  6. 모듈

선언 스타일

바르

를 사용하여 선언된 식별자는 전역 컨텍스트에서 직접 선언되는 경우를 제외하고

var 함수 범위 를 가집니다. 이 경우 전역 개체의 속성으로 추가되고 전역 범위를 갖습니다.

함수 에서 사용하기 위한 별도의 규칙이 있습니다

eval

.

let과 const

식별자를 사용하여 선언

let

하고

const 블록 범위

를 가집니다. 단, 전역 컨텍스트에서 직접 선언되는 경우에는 전역 범위를 갖습니다.참고:

let

,

const

var 모두 게양

됩니다. 이는 정의의 논리적 위치가 둘러싸는 범위(블록 또는 함수)의 맨 위에 있음을 의미합니다.

let

그러나 를 사용 하여 선언된 변수는

const

컨트롤이 소스 코드의 선언 지점을 통과할 때까지 읽거나 할당할 수 없습니다. 임시 기간은 일시적 데드 존으로 알려져 있습니다.

 

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

간접적으로 사용되는 경우 전역 개체의 속성으로 배치됩니다.

 

x

다음은 이름 ,

y

z

이 함수 외부에서 의미가 없기 때문에 ReferenceError 를 발생시킵니다

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)

 

 

y

다음은 및 에 대한 ReferenceError를 발생

z

시키지만

x

의 가시성이

x

블록에 의해 제한되지 않기 때문에 에 대해서는 발생하지 않습니다.

if

,

for

및 와 같은 제어 구조의 본문을 정의하는 블록은

while

유사하게 동작합니다.

 

{
    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

...이 동작 때문에 in 루프 를 사용하여 선언된 변수를 닫을 때 주의해야 합니다 .

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

 

let

전역

const

컨텍스트에서 전역 개체에 속성을 추가하지 않지만 여전히 전역 범위를 가집니다.

 

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

 

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

 

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

 

Catch 블록 매개변수는 catch-block 본문으로 범위가 지정됩니다.

 

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에서 모든 함수 개체에는 생성된 실행 컨텍스트 (스택 프레임) 의 어휘 환경

[[Environment]]

대한 참조인 숨겨진 참조가 있습니다.함수를 호출하면 숨겨진

[[Call]]

메서드가 호출됩니다. 이 메서드는 새 실행 컨텍스트를 만들고 새 실행 컨텍스트와 함수 개체의 어휘 환경 사이에 링크를 설정합니다.

[[Environment]]

함수 개체의 값을 새 실행 컨텍스트의 어휘 환경에 있는

외부 참조

필드로 복사하여 이를 수행합니다.새 실행 컨텍스트와 함수 개체의 어휘 환경 사이의 이 링크를

클로저

라고 합니다 .따라서 JavaScript에서 범위는 외부 참조에 의해 "체인"으로 함께 연결된 어휘 환경을 통해 구현됩니다. 이 어휘 환경 체인을 범위 체인이라고 하며 식별자 확인 은 일치하는 식별자에 대한

체인을 검색하여 발생합니다.

자세히 알아

보기

 

반응형

댓글