programing

JavaScript의 변수 범위는 어떻게 됩니까?

projobs 2023. 1. 14. 10:06
반응형

JavaScript의 변수 범위는 어떻게 됩니까?

javascript의 변수 범위는 어떻게 되나요?기능 외부가 아니라 내부가 동일한 범위입니까?아니면 그게 중요한가요?또한 변수가 글로벌하게 정의되어 있는 경우 변수는 어디에 저장됩니까?

TLDR

JavaScript에는 사전(스태틱이라고도 함) 범위 지정 및 닫힘 기능이 있습니다.즉, 소스 코드를 보고 식별자의 범위를 알 수 있습니다.

4개의 스코프는 다음과 같습니다.

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

및 범위의 됩니다.var 범위 (기능 범위),let 스코프및 (블록 스코프),const(일부러)대부분의 다른 형식의 식별자 선언에는 블록스코프가 strict 모드로 설정되어 있습니다.

개요

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

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

스코프는 상위 실행 컨텍스트의 어휘 환경에 대응하는 네스트 내의 각 레벨을 포함한 어휘 환경의 링크드 네스트에 의해 형성된다.

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

식별자 확인은 한 방향(외부)에서만 발생합니다.이와 같이 외부 어휘 환경은 내부 어휘 환경을 "확인"할 수 없습니다.

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

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

식별자는 다음과 같은 방법으로 선언할 수 있습니다.

  1. var,let ★★★★★★★★★★★★★★★★★」const
  2. 함수 파라미터
  3. Catch block 파라미터
  4. 함수 선언
  5. 명명된 함수 식
  6. 에 암묵적으로 ""가 "(":")var 모드 비타임 모드)
  7. import(START)
  8. eval

일부 로케이션 식별자는 선언할 수 있습니다.

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

선언 스타일

변화하다

를 사용하여 var 는 글로벌 컨텍스트에서 직접 선언되는 경우를 제외하고 함수 범위를 가집니다.이 경우 글로벌오브젝트에 속성으로 추가되어 글로벌 범위를 가집니다.에서의 사용에는 별도의 규칙이 있습니다.eval★★★★★★★★★★★★★★★★★★.

임대 및 건설

를 사용하여 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`!

함수 매개 변수 이름

기능 파라미터 이름은 기능 본문까지 범위가 지정됩니다.여기에는 약간의 복잡성이 있습니다.기본 인수로 선언된 함수는 함수 본문이 아닌 파라미터 목록 위로 닫힙니다.

함수 선언

함수 선언에는 블록 스코프가 strict 모드로, 함수 스코프가 non-strict 모드로 설정되어 있습니다.주의: 엄격하지 않은 모드는 다양한 브라우저의 기발한 이력 구현에 기초한 복잡한 규칙 세트입니다.

명명된 함수 식

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

글로벌 개체에 암묵적으로 정의된 속성

엄격하지 않은 모드에서는 글로벌오브젝트가 스코프 체인의 맨 위에 있기 때문에 글로벌오브젝트에 암묵적으로 정의된 속성은 글로벌스코프를 가집니다.strict 모드에서는, 이것들은 허가되지 않습니다.

평가하다

»eval ""를 사용하여 , ""var에 배치됩니다, in if if if willeval는 글로벌 객체의 속성으로 간접적으로 사용됩니다.

이 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)

에, 「ReferenceError」의 「」를 합니다.y ★★★★★★★★★★★★★★★★★」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

다 in in inx는 루프 밖에서 볼 수.var에는 기능 범위가 있습니다.

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

으로 인해 ...을 사용하여 때 .이 동작으로 인해 선언된 변수를 닫을 때 주의해야 합니다.var변수에는 단 한 .x여기서 선언되어 논리적으로 루프 밖에 있습니다.

은 인쇄물입니다.5, 5회 인쇄, 5회 인쇄, 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

은 인쇄물입니다.undefinedx블록 범위입니다.1번" " " 의 let는 변수라는 의 다른 변수에 각 것을 의미합니다.x)var 정수입니다.0 through를 통해.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 보이기 입니다.xundefined되지 않았기 입니다(이유는 가 초기화되지 않았기 때문입니다).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

캐치 블록 매개변수는 캐치 블록 본문으로 범위가 지정됩니다.

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

엄격하지 않은 모드에서는 글로벌개체에 암묵적으로 정의된 속성은 글로벌하게 범위가 지정됩니다.strict 모드에서는 에러가 발생합니다.

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

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

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

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

후드 아래에서의 동작

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

모든 JavaScript가 .[[Environment]]참조는 참조가 생성된 실행 컨텍스트(스택 프레임)의 사전 환경에 대한 참조입니다.

" " " " 가 표시됩니다.[[Call]]메서드가 호출됩니다.이 메서드는 새로운 실행 콘텍스트를 생성하여 새로운 실행 콘텍스트와 함수 객체의 어휘 환경 간의 링크를 확립합니다.하려면 , 「」를 합니다.[[Environment]]function-object의 값을 새로운 실행 컨텍스트의 어휘 환경 상의 외부 참조 필드로 변환합니다.

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

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

자세한 것은 이쪽.

Javascript는 스코프 체인을 사용하여 특정 함수의 스코프를 설정합니다.일반적으로 하나의 글로벌 스코프가 있으며 정의된 각 함수에는 고유한 중첩 스코프가 있습니다.다른 기능 내에 정의된 기능에는 외부 기능과 연결된 로컬 스코프가 있습니다.스코프를 정의하는 것은 항상 소스의 위치입니다.

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

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

글로벌하게 선언된 변수는 글로벌 범위를 가집니다.함수 내에서 선언된 변수는 해당 함수로 범위가 지정되고 같은 이름의 전역 변수가 섀도우됩니다.

(실제 JavaScript 프로그래머가 다른 답변에서 지적할 수 있는 많은 미묘함이 있을 것입니다.특히 이 페이지를 접하게 된 것은 정확히 무엇이냐 하는 것입니다.this언제든지 의미합니다.이 소개 링크만으로도 충분히 시작할 수 있을 것입니다.)

구식 JavaScript

전통적으로 JavaScript에는 두 가지 유형의 범위만 있습니다.

  1. Global Scope : 변수는 어플리케이션 시작부터 어플리케이션 전체에 걸쳐 알려져 있습니다(*).
  2. Functional Scope : 변수는 선언된 함수 에서 함수(*)의 시작부터 알 수 있습니다.

그 차이를 설명하는 다른 많은 답변이 있기 때문에 이에 대해서는 자세히 설명하지 않겠습니다.


최신 JavaScrivate

최신 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는 첫 번째 루프에서만 인식되며 이전과 이후는 인식되지 않습니다. 지지 yet yet yet yet yet yet yet yet yeti는 기능 전체에 알려져 있습니다.

또한 블럭 범위 변수는 중단되지 않기 때문에 선언되기 전에 알 수 없는 것으로 간주하십시오.또한 동일한 블록 범위 변수를 동일한 블록 내에서 다시 선언할 수 없습니다.따라서 블록 범위 변수는 글로벌 또는 기능 범위 변수보다 오류가 발생하기 쉬우며, 여러 선언이 있더라도 오류가 발생하지 않습니다.


현재 블록 범위 변수를 사용하는 것이 안전합니까?

현재 사용해도 안전한지 여부는 환경에 따라 달라집니다.

  • 서버측 JavaScript 코드(Node.disclosed(비활성화))를 작성하는 경우,let★★★★★★ 。

  • 클라이언트 측 JavaScript 코드를 작성하고 브라우저 기반 트랜스필러(트레이서 또는 바벨 스탠드아론의 등)를 사용하는 경우 안전하게let스테이트먼트. 단, 퍼포먼스에 관해서는 코드가 최적이 아닐 수 있습니다.

  • 클라이언트 측 JavaScript 코드를 작성하고 노드 기반 트랜스필러(traceur스크립트 또는 Babel 등)를 사용하는 경우 안전하게let 되어야 합니다.또한 브라우저는 변환된 코드만 인식하므로 성능 단점은 제한되어야 합니다.

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

    은 음음음음음 that these를 지원하지 않는 브라우저입니다.let :::

    • Internet Explorer 10 이하
    • 파이어폭스 43 이하
    • Safari 9 이하
    • Android 브라우저 4 이하
    • 오페라 27 이하
    • 쵸메 40 이하
    • Opera Mini 및 Blackberry 브라우저의 모든 버전

여기에 이미지 설명 입력


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

를 하는 브라우저의 과 같습니다.let이 답변을 읽을 때의 스테이트먼트는, 이 페이지참조해 주세요.


(*) JavaScript 변수가 호이스트되기 때문에 글로벌 및 기능 범위 변수를 선언하기 전에 초기화하고 사용할 수 있습니다.즉, 선언은 항상 스코프의 최상위에 있습니다.

다음은 예를 제시하겠습니다.

<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>

폐쇄와 개인 회원을 만드는 데 사용하는 방법을 조사해야 할 것입니다.

제가 알기로는 Javascript는 일반적인 C 블록 범위와 비교하여 기능 수준의 범위를 가지고 있는 것으로 알고 있습니다.

여기 그 주제에 대한 좋은 기사가 있다.

"Javascript 1.7"(Javascript에 대한 Mozilla의 확장자)에서는 다음 문장으로 블록 범위 변수를 선언할 수도 있습니다.

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

Brendan Eich가 원래 설계했을 때 JavaScript에서 스코핑하는 아이디어는 HyperCard 스크립트 언어 HyperTalk에서 비롯되었습니다.

이 언어에서 표시는 인덱스 카드 스택과 유사하게 수행되었습니다.배경이라고 하는 마스터 카드가 있었습니다.그것은 투명했고 맨 아래 카드로 볼 수 있다.이 베이스 카드의 컨텐츠는, 그 위에 배치되어 있는 카드로 공유됩니다.맨 위에 배치된 각 카드에는 이전 카드보다 우선하는 자체 콘텐츠가 있지만 필요에 따라 이전 카드에 액세스할 수 있습니다.

이것이 바로 JavaScript 범위 지정 시스템이 설계된 방법입니다.이름만 다를 뿐이지JavaScript 내의 카드는 ExecutionECMA Contexts라고 불립니다.각각의 콘텍스트에는, 3개의 주요한 부분이 있습니다.가변 환경, 어휘 환경 및 이 바인딩.카드 참조로 돌아가면, 사전 환경에는 스택 하부에 있는 이전 카드의 모든 컨텐츠가 포함되어 있습니다.현재 컨텍스트는 스택의 맨 위에 있으며, 이 컨텍스트에 선언된 모든 컨텐츠는 가변 환경에 저장됩니다.이름 충돌의 경우 변수 환경이 우선합니다.

이 바인딩은 포함된 개체를 가리킵니다.가 " " "가 될 수 " 등변경되지 않고 될 수 .window또는 생성자 함수입니다.

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

이것이 기술적인 설명입니다.실제로 JavaScript에서는 다음 사항을 기억해야 합니다.

  • 범위는 엄밀히 말하면 '실행 컨텍스트'입니다.
  • 콘텍스트는 변수가 저장되는 환경의 스택을 형성합니다.
  • 스택의 맨 위가 우선됩니다(맨 아래가 글로벌콘텍스트).
  • 각 함수는 실행 컨텍스트를 생성합니다(단, 항상 새로운 바인딩은 아닙니다).

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

i) 외부 콘텍스트a = 1의 가변 환경을 가지고 있습니다.
ii) IIFE 문맥은 a=1의 어휘 환경을 가지지만 스택에서 우선하는 a=6의 가변 환경을 가진다.
iii) 반환된 함수 문맥은 a = 6의 사전 환경을 가지며 호출 시 경보에서 참조되는 이다.

여기에 이미지 설명 입력

1) 글로벌 스코프, 기능 스코프, with 및 catch 스코프가 있습니다.변수에는 일반적으로 '블록' 수준의 범위가 없습니다.with 문과 catch 문장은 블록에 이름을 추가합니다.

2) 스코프는 함수에 따라 글로벌 스코프까지 네스트됩니다.

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

편집: ECMAAScript 6(Harmony)은 Let을 지원하도록 설계되어 있으며, Chrome은 'Harmony' 플래그를 사용할 수 있다는 것을 알고 있기 때문에 아마 지원할 수 있을 것입니다.

블록 레벨의 범위를 서포트하는 것으로 합니다만, 그러기 위해서는 키워드를 사용할 필요가 있습니다.

편집: Benjamin의 지적과 댓글의 catch 스테이트먼트를 바탕으로 투고를 편집하여 추가하였습니다.with 문과 catch 문 모두 각각의 블록에 변수를 도입합니다.이것은 블록 범위입니다.이러한 변수는 전달된 객체의 속성에 따라 별칭이 지정됩니다.

 //chrome (v8)

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

편집: 명확한 예:

test1은 block을 사용하여 범위 지정되지만 a.test1과 에일리어스 지정됩니다.'Var test1'은 상위 어휘 컨텍스트(함수 또는 전역)에 새 변수 test1을 생성합니다. 단, 이 값은 --의 속성이 아닙니다.

함수에서 변수가 이미 정의되어 있으면 var가 noop인 것처럼 개체에서 가져온 이름에 대해서도 noop이 됩니다.이미 정의되어 있는 이름에 대해 조금만 주의를 기울이면 훨씬 더 안전해질 거야.이 때문에 개인적으로는 사용하지 않습니다.

JavaScript를 처음 접하는 많은 사람들은 상속이 기본적으로 언어로 가능하며, 함수 범위가 지금까지 유일한 범위라는 것을 이해하는 데 어려움을 겪고 있다는 것을 알게 되었습니다.작년 말에 쓴 JSPretty라는 미용사의 연장을 제공했습니다.피쳐 색상은 코드의 함수 범위를 나타내며 항상 해당 범위에서 선언된 모든 변수에 색상을 연관시킵니다.닫힘은 한 스코프의 색상을 가진 변수가 다른 스코프에서 사용되는 경우 시각적으로 표시됩니다.

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

다음 사이트에서 데모를 참조하십시오.

코드 표시 위치:

현재 이 기능은 16개의 중첩 함수를 지원하지만 현재 글로벌 변수를 색칠하지는 않습니다.

인라인 핸들러

프런트 엔드 코더가 자주 발생하는 매우 일반적인 문제는 HTML 내의 인라인이벤트 핸들러에 표시되는 범위입니다.예를 들어 다음과 같습니다.

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

사용하는 변수의 .on*Atribute reference는 다음 중 하나여야 합니다.

  • global(거의 항상 글로벌 변수를 참조하는 인라인핸들러)
  • 서서의예예:querySelector가 '''를 document.querySelector 희귀)
  • 핸들러가 연결되어 있는 요소의 특성(위와 같은, 희귀)

그렇지 않으면 핸들러가 호출될 때 ReferenceError가 표시됩니다.예를 들어 인라인핸들러가 내부에 정의되어 있는 함수를 참조하는 경우 window.onload ★★★★★★★★★★★★★★★★★」$(function() {인라인 핸들러는 글로벌스코프 내의 변수만 참조할 수 있고 함수는 글로벌하지 않기 때문에 참조는 실패합니다.

window.addEventListener('DOMContentLoaded', () => {
  function foo() {
    console.log('foo running');
  }
});
<button onclick="foo()">click</button>

document또한 인라인 핸들러는 2개의 블록 에서 호출되기 때문에 핸들러가 연결되어 있는 요소의 속성은 인라인핸들러 내의 스탠드아론 변수로 참조될 수 있습니다.document, 엘리먼트에 1개요.이러한 핸들러내의 변수의 스코프 체인은 지극히 무의미합니다.또, 현용 이벤트 핸들러에서는, 글로벌한 기능이 필요하게 됩니다(불필요한 글로벌 오염은 피할 필요가 있습니다).

인라인 핸들러 내부의 스코프 체인은 매우 이상하고 인라인 핸들러가 동작하려면 글로벌 오염이 필요하며 인라인 핸들러는 인수를 전달할 때 추한 문자열 이스케이프가 필요할 수 있으므로 이를 피하는 것이 더 쉬울 수 있습니다.대신 Javascript를 사용하여 이벤트 핸들러를 첨부합니다(예:addEventListenerHTML " " " " " ) 。

function foo() {
  console.log('foo running');
}
document.querySelector('.my-button').addEventListener('click', foo);
<button class="my-button">click</button>

모듈(<script type="module">)

로 하자면, 보통과 , on, 른, 른, 른, on, on, on, on, on, on, on, on, on과는 달리<script>태그는 최상위 레벨에서 실행되며 ES6 모듈 내의 코드는 자체 개인 범위에서 실행됩니다.인 「」의 되어 있는 .<script>할 수 있습니다.<script>을 사용하다

<script>
const foo = 'foo';
</script>
<script>
console.log(foo);
</script>

그러나 ES6 모듈의 최상위 레벨은 글로벌하지 않습니다.ES6 모듈의 상단에 선언된 변수는 명시적으로 표시되지 않는 한 해당 모듈 내에서만 표시됩니다.exported 한 ed를 합니다.

<script type="module">
const foo = 'foo';
</script>
<script>
// Can't access foo here, because the other script is a module
console.log(typeof foo);
</script>

ES6의 합니다.<script>모듈은 글로벌한 모든 변수를 참조할 수 있으며 모듈이 명시적으로 설계되지 않은 한 모듈 내의 어떤 변수도 참조할 수 없습니다.

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

  1. Global Scope : Global은 윈도 레벨의 범위일 뿐입니다.여기서 변수는 애플리케이션 전체에 존재합니다.
  2. Functional Scope : 함수 내에서 선언된 변수var키워드에는 기능 범위가 있습니다.

함수를 호출할 때마다 변수 범위 개체가 생성되고(및 범위 체인에 포함됨) JavaScript에서 변수가 이어집니다.

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

스코프 체인 -->

  1. 레벨 - 창준수 -a ★★★★★★★★★★★★★★★★★」outer기능은 스코프 체인에서 최상위 수준입니다.
  2. 「신규」라고 variable scope object 스코프 체인에 ) (「」)가 되어 있습니다.b그 안에.

서 변수 '''가a필요한 경우 가장 가까운 변수 범위를 검색하고 변수가 없는 경우 변수 범위 체인의 다음 개체로 이동합니다.이 경우 윈도우 레벨입니다.

암호를 실행합니다.이것이 범위 지정에 대한 아이디어를 줄 수 있기를 바란다

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);

글로벌 범위:

글로벌 변수는 글로벌 스타(재키 찬, 넬슨 만델라)와 똑같다.응용 프로그램의 모든 부분에서 액세스(값 가져오기 또는 설정)할 수 있습니다.글로벌 행사는 글로벌 이벤트(새해, 크리스마스)와 같다.애플리케이션의 어느 부분에서도 이러한 기능을 실행(호출)

//global variable
var a = 2;

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

로컬 범위:

만약 당신이 미국에 있다면, 당신은 악명 높은 유명인사 킴 카다시안을 알고 있을 것이다.하지만 미국 밖의 사람들은 그녀를 알아보지 못할 것이다.그녀는 지역 스타로 자신의 영역에 묶여 있다.

지역 변수는 지역별과 같습니다.스코프 내에서만 액세스(값 가져오기 또는 설정)할 수 있습니다.로컬 기능은 로컬 이벤트와 같습니다. 해당 범위 내에서만 실행할 수 있습니다.범위 밖에서 액세스하려면 참조 오류가 발생합니다.

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    

범위에 대한 자세한 내용은 이 문서를 참조하십시오.

다른 답변에 추가하여 스코프는 선언된 모든 식별자(변수)의 룩업목록이며, 현재 실행 중인 코드에서 이러한 식별자(변수)에 어떻게 액세스할 수 있는지에 대한 엄격한 규칙 집합을 적용합니다.이 검색은 LHS(왼쪽) 기준인 변수에 할당하기 위한 것일 수도 있고 RHS(오른쪽) 기준인 값을 검색하기 위한 것일 수도 있다.이러한 룩업은 JavaScript 엔진이 코드를 컴파일 및 실행할 때 내부적으로 수행하는 작업입니다.

그래서 이런 관점에서, 저는 Kyle Simpson의 Scopes and Closes 전자책에서 찾은 사진이 도움이 될 것이라고 생각합니다.

이미지

그의 전자책에서 인용:

빌딩은 프로그램의 중첩된 범위 규칙 집합을 나타냅니다.건물의 1층은 현재 실행 중인 범위를 나타냅니다.빌딩의 최상위 레벨은 글로벌 스코프입니다.LHS 및 RHS 참조를 해결하려면 현재 층을 살펴보고, 찾을 수 없는 경우 엘리베이터를 타고 다음 층까지 이동한 후 다음 층까지 살펴봅니다.최상층(글로벌 범위)에 도착하면 원하는 것을 찾거나 찾을 수 없습니다.하지만 넌 어쨌든 멈춰야 해.

언급할 가치가 있는 주의사항 중 하나는 "스코프 조회가 첫 번째 일치를 찾으면 중지됩니다."입니다.

이 "범위 수준" 개념은 중첩된 함수에서 검색되는 경우 새로 생성된 범위를 사용하여 "이"를 변경할 수 있는 이유를 설명합니다. 모든 세부사항에 대한 링크입니다. javascript 스코프에 대해 알고 싶은 모든 것.

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

  • 각 var 선언의 범위는 가장 즉시 둘러싸인 함수와 관련된다.
  • var 선언을 위한 둘러싸는 함수가 없는 경우 글로벌 스코프입니다.

따라서 함수 이외의 블록은 새로운 스코프를 작성하지 않습니다.따라서 for-loops가 외부 범위 변수를 덮어쓰는 이유는 다음과 같습니다.

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 범위 지정에 관해 알아야 할 것은 거의 이것뿐입니다.단, 다음과 같습니다.

  • 예외 변수 자체에 대해서만 새로운 범위를 도입하고, 다른 변수에는 새로운 범위가 없습니다.
  • with-filename도 예외이지만 with-filename을 사용하는 것은 매우 권장되지 않습니다(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with)

따라서 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);

이것은 직관에 반하는 것처럼 보일 수 있지만, 명령어 디자이너의 관점에서 보면 일리가 있습니다.

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

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

const95%의 경우에 사용해야 합니다.변수 참조가 변경되지 않도록 합니다.어레이, 오브젝트 및 DOM 노드 속성은 변경될 수 있으며 다음과 같이 될 수 있습니다.const.

let재할당이 예상되는 모든 변수에 사용해야 합니다.을 뜻합니다.넘어 값을 는, 「」를 사용해 .let.

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

이 신기한 예를 들어 보세요.다음 예에서는 a가 0으로 초기화된 수치일 경우 0과 1이 표시됩니다.단, 가 오브젝트이며 javascript는 복사본이 아닌 포인터를 f1에 전달합니다.그 결과 두 번 모두 동일한 경보가 발생합니다.

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

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);

글로벌 스코프, 블록에 관계없이 기능 전체에 사용할 수 있는 로컬 스코프, 블록이 사용된 블록, 스테이트먼트 또는 식에만 사용할 수 있는 블록 스코프의 3가지 스코프가 있는 것으로 알고 있습니다.글로벌 및 로컬 스코프는 함수 내 또는 외부에서 키워드 'var'로 표시되고 블록 스코프는 키워드 'let'으로 표시됩니다.

글로벌 스코프와 로컬 스코프 밖에 없다고 생각하시는 분은, 왜 Mozilla가 JS의 블록 스코프의 뉘앙스를 설명하는 페이지 전체를 가지고 있는지 설명해 주세요.

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

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 
    }
}

저는 인정된 답변이 정말 마음에 드는데, 이것을 추가하고 싶습니다.

Scope는 선언된 모든 식별자(변수)의 룩업목록을 수집 및 유지 보수하고 현재 실행 중인 코드에서 이들 ID(변수)에 액세스할 수 있는 방법에 대한 엄격한 규칙 집합을 적용합니다.

범위는 식별자 이름으로 변수를 검색하기 위한 규칙 집합입니다.

  • 즉시 범위에서 변수를 찾을 수 없는 경우 엔진은 다음 외측 포함 범위를 참조하여 가장 바깥쪽(일명 글로벌) 범위에 도달할 때까지 계속합니다.
  • 변수(식별자)를 검색할 위치와 방법을 결정하는 규칙 집합입니다.이 조회는 LHS(왼쪽) 기준인 변수에 할당하기 위한 것일 수도 있고 RHS(오른쪽) 기준인 값을 검색하기 위한 것일 수도 있습니다.
  • LHS 참조는 할당 조작에 의해 작성됩니다.스코프 관련 할당은 = 연산자를 사용하거나 인수를 함수 파라미터에 전달하여 수행할 수 있습니다.
  • JavaScript 엔진은 실행하기 전에 먼저 코드를 컴파일하고, 그렇게 함으로써 var a = 2와 같은 문을 두 개의 별도 단계인 1st로 나눕니다.먼저 var a를 사용하여 해당 범위에서 선언합니다.코드 실행 전 첫머리에서 실행됩니다.두 번째.나중에 a = 2로 변수를 검색하고(LHS 참조), 발견된 변수를 할당합니다.
  • LHS 및 RHS 참조 룩업은 모두 현재 실행 중인 스코프에서 시작됩니다.필요한 경우(즉, 원하는 것을 찾을 수 없는 경우), 글로벌(상층)에 도달하여 정지하거나 찾을 수 없을 때까지 한 번에 1개의 스코프(플로어)로 네스트된 스코프(플로어) 위로 이동합니다.RHS 참조가 채워지지 않으면 ReferenceError가 느려집니다.LHS 참조가 채워지지 않으면 해당 이름의 자동 글로벌(Strict 모드가 아닌 경우) 또는 ReferenceError(Strict 모드인 경우)가 암묵적으로 생성됩니다.
  • 스코프는, 각각이 컨테이너 또는 버킷으로서 기능하는 일련의 「코너」로 구성되어 식별자(코너, 함수)가 선언됩니다.이 버블들은 서로 안에 깔끔하게 자리 잡고 있으며, 이 네스팅은 작성자 시간에 정의되어 있습니다.

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 foo의 함수에 .foo foo는 foo foo의 에 있습니다.innerFunc그 자체입니다.은 foo 됩니다.innerFunc.
  2. , 함수 수 .innerFunc그 자체입니다.따라서 스코프 체인을 올라가야 합니다.먼저 외부 함수에 대해 살펴봅니다.innerFunc정의되었습니다.이게 함수입니다.outerFuncouterFunc '는 '변수바를 볼 수 있어요. '아주'라고 합니다.
  3. foobar를 innerFunc에서 찾을 수 없습니다.따라서 스코프 체인을 innerFunc 스코프로 올라가야 합니다.여기서도 찾을 수 없습니다. 글로벌 범위(즉, 가장 바깥쪽 범위)로 한 단계 더 올라갑니다.여기서 'global' 문자열을 유지하는 변수 foobar를 찾을 수 있습니다.스코프 체인을 상승시킨 후 변수를 찾지 못한 경우 JS 엔진은 referenceError를 발생시킵니다.

ES6 2015) (ES 2015)

및 이 에도 됩니다.ES6그러나 변수를 선언하는 새로운 방법이 도입되었다.하다

  • let 변수를 ( 「블록 범위 변수」).
  • const 할 수 를 만듭니다.

장장큰의 큰 var ★★★★★★★★★★★★★★★★★」let/const라는 것이다.var는 함수 인 반면, 「」는 「」입니다.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로 가 letVar로 선언되었기 때문입니다.let록록스스 스다다다다다각 블록 외부에 존재하지 않기 때문에 if 블록 밖에서는 변수에 액세스할 수 없습니다.

EcmaScript5에서는 주로 로컬 스코프와 글로벌 스코프의 2가지 스코프가 있습니다만, EcmaScript6에서는 로컬 스코프, 글로벌 스코프 및 블록 스코프라고 불리는 새로운 스코프의 3가지 스코프가 있습니다.

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

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.
}

ECMAScript 6에서는 let 키워드와 const 키워드가 도입되었습니다.이러한 키워드는 var 키워드 대신 사용할 수 있습니다.var 키워드와는 달리 let 키워드와 const 키워드는 block 문의 로컬스코프 선언을 지원합니다.

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

JavaScript의 변수 범위는 어떻게 됩니까?
(function foo() { console.log(foo) })();
console.log(typeof foo); // undefined, because `foo` is scoped to its own expression

//but, like this
(function foo() {
    console.log('1:', foo) // function foo
    foo = 100
    console.log('2:', foo) // function foo, is not 100, why?
})()

JavaScript에는 두 가지 유형의 스코프가 있습니다.

  1. Global Scope: Global Scope에서 공지되는 변수는 프로그램 내 어디에서나 매우 원활하게 사용할 수 있습니다.예를 들어 다음과 같습니다.

    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
    }
    

언급URL : https://stackoverflow.com/questions/500431/what-is-the-scope-of-variables-in-javascript

반응형