프로그래밍 언어/HTML,CSS,JS

JavaScript에서 변수의 범위에 대해서

Rateye 2021. 11. 30. 09:44
728x90
반응형
질문 : JavaScript에서 변수의 범위는 무엇입니까?

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

답변

 


TLDR

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

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

  1. Global - 모든 것이 표시
  2. Function - 함수(및 하위 함수 및 블록) 내에서 볼 수 있습니다.
  3. Block - 블럭(및 해당 하위 블럭) 내에서 볼 수 있습니다.
  4. Module - 모듈 내에서 볼 수 있음

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

개요

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

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

범위는 어휘 환경의 링크 된 중첩으로 구성되며 중첩의 각 수준은 조상 실행 컨텍스트의 어휘 환경에 해당합니다.

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

식별자 확인은 한 방향, 즉 바깥쪽으로 만 발생합니다. 이런 식으로 외부 어휘 환경은 내부 어휘 환경을 "볼"수 없습니다.

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

  1. 식별자가 선언된 방법
  2. 식별자가 선언된 위치
  3. strict mode인지 또는 non-strict mode인지 여부

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

  1. var, let, const
  2. Function 매개변수
  3. Catch block 매개변수
  4. Function 선언
  5. 명명된 function 표현식
  6. 글로벌 개체에 암시적으로 정의된 속성(즉, 엄격하지 않은 모드에서 var 누락)
  7. import statements
  8. eval

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

  1. Global context
  2. Function body
  3. 일반 블록
  4. 제어 구조의 상단(예: 루프, if, while 등)
  5. 제어구조체
  6. 모듈

선언 스타일

var

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

건설하다

letconst 사용하여 선언 된 식별자는 전역 컨텍스트에서 직접 선언 된 경우를 제외하고 블록 범위 를 갖습니다.이 경우 전역 범위가 있습니다.

참고 : let , constvar 가 모두 호이스트 됩니다. 이것은 논리적 정의 위치가 둘러싸는 범위 (블록 또는 기능)의 맨 위에 있음을 의미합니다. letconst 사용하여 선언 된 변수는 컨트롤이 소스 코드의 선언 지점을 통과 할 때까지 읽거나 할당 할 수 없습니다. 중간 기간을 일시적인 데드 존이라고합니다.

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

Function 매개 변수 이름

함수 매개 변수 이름은 함수 본문으로 범위가 지정됩니다. 여기에는 약간의 복잡성이 있습니다. 기본 인수로 선언 된 함수는 함수 본문이 아닌 매개 변수 list에서 닫힙니다.

Function 선언

함수 선언에는 엄격 모드의 블록 범위와 비 엄격 모드의 함수 범위가 있습니다. 참고 : 비 엄격 모드는 여러 브라우저의 기발한 역사적 구현을 기반으로하는 복잡한 일련의 새로운 규칙입니다.

명명 된 Function 표현식

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

글로벌 개체에 암시적으로 정의된 속성(즉, 엄격하지 않은 모드에서 var 누락)

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

eval

eval var 를 사용하여 선언 된 변수는 현재 범위에 배치되거나, eval 이 간접적으로 사용되는 경우 전역 개체의 속성으로 배치됩니다.

반응형

예를 들어

다음은 x , y , z f 외부에서 의미가 없기 때문에 ReferenceError를 발생시킵니다.

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)

x 의 가시성이 블록에 의해 제한되지 yz 에 대해서는 ReferenceError를 발생 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

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

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

다음은 x 가 블록 범위이기 때문에 undefined 콜백은 비동기 적으로 하나씩 실행됩니다. 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

다음은 x 의 가시성이 블록에 의해 제한되지 ReferenceError 그러나 변수가 초기화 undefined 인쇄됩니다 if 문 때문에).

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

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

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

다음은 x 의 가시성이 블록에 의해 제한 ReferenceError

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

 

hood 아래에서 작동하는 방식

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

JavaScript에서 모든 함수 객체는 생성 된 실행 컨텍스트 (스택 프레임) 의 어휘 환경 에 대한 참조 인 [[Environment]]

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

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

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

알아 보다 .

출처 : https://stackoverflow.com/questions/500431/what-is-the-scope-of-variables-in-javascript
728x90
반응형