>웹 프론트엔드 >JS 튜토리얼 >JavaScript의 범위에 대한 자세한 소개(코드 예)

JavaScript의 범위에 대한 자세한 소개(코드 예)

不言
不言앞으로
2019-03-11 16:59:121701검색

이 기사의 내용은 JavaScript의 범위에 대한 자세한 소개(코드 예제)입니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

거의 모든 프로그래밍 언어에는 범위라는 개념이 있는데, 범위란 정확히 무엇을 말하는 걸까요? 범위는 프로그래밍 언어에서 변수를 정의할 때 변수가 저장되고 액세스되는 방식에 대한 규칙 집합입니다. 다음으로 이 규칙 집합이 어떻게 설정되는지 살펴보겠습니다.

편집 원리

전통적인 컴파일 언어에는 코드 실행 전에 컴파일 프로세스가 있습니다.

  • 단어 분할/어휘 분석: 코드 구문을 어휘 단위라고도 하는 의미 있는 코드 블록으로 분해합니다.
  • 파싱/문법 분석: 어휘 단위를 레벨별로 중첩된 문법 규칙이 있는 트리 구조로 변환합니다. 이는 AST(추상 구문 트리)라고도 합니다.
  • 코드 생성: AST를 구문 분석하여 기계 명령어

및 기존 컴파일 언어로 변환합니다. js의 컴파일과 실행은 별도로 실행되지 않으며, 대부분의 경우 짧은 컴파일 과정에서 최적의 성능을 얻기 위해 js 엔진은 일반 컴파일러보다 더 복잡합니다. , 이제 js의 컴파일 프로세스를 살펴보겠습니다. var a = 2 컴파일을 예로 들어 보겠습니다.

  • var a를 발견하면 컴파일러는 이 이름을 가진 변수가 동일한 범위에 이미 존재하는지 범위에 묻습니다. 수집. 그렇다면 컴파일러는 선언을 무시하고 컴파일을 계속합니다. 그렇지 않으면 현재 범위의 컬렉션에서 새 변수 a를 선언하도록 범위에 요청합니다
  • 그런 다음 컴파일러는 엔진에 필요한 런타임 코드를 생성합니다. 할당 작업 a=2를 처리하는 데 사용됩니다. 엔진이 실행 중일 때 먼저 현재 범위 세트에 a라는 변수가 있는지 범위에 묻습니다. 그렇지 않은 경우 엔진은 이 변수를 사용합니다. 엔진이 최종적으로 a를 찾으면 해당 변수에 2를 할당합니다. 그렇지 않으면 엔진에서 예외가 발생합니다.

어휘 범위

범위에는 일반적으로 두 가지 작업 모델이 있습니다. 첫 번째는 대부분의 프로그래밍 언어에서 사용되는 어휘 범위이고 다른 하나는 동적 범위입니다. Bash 스크립트와 같은 도메인은 사용합니다. 동적 범위. 어휘 범위는 어휘 단계에서 정의된 범위입니다. 어휘 범위는 코드 작성 시 변수와 블록 범위를 작성하는 위치에 따라 결정되는 반면 동적 범위는 변수 사용에 따라 결정됩니다. 위치별로. 예를 살펴보겠습니다.

function foo(a) {
  var b = a * 2;
  function bar(c) {
    console.log(a, b, c)
  }
  bar(b * 3)
}
foo(2)

우선 스코프가 총 몇 개인지 분석해 볼까요?

  1. foo 변수가 포함된 전역 범위
  2. a, b, bar 변수가 포함된 foo 함수에 의해 생성된 범위
  3. c 변수가 포함된 bar 함수에 의해 생성된 범위

다음으로 변수 분석 검색 프로세스에서 엔진은 console.log()를 실행할 때 세 가지 변수 a, b 및 c에 대한 참조를 찾아야 합니다. 먼저 bar()의 가장 안쪽 범위에서 시작합니다. 따라서 foo().) 범위로 올라가서 여기에서 a를 찾고 검색을 중지하며 검색 프로세스는 b와 c에 대해 동일합니다. 범위 검색은 항상 런타임의 가장 안쪽 수준에서 시작하여 일치하는 첫 번째 변수가 나타날 때까지 바깥쪽으로 검색합니다.

함수 범위

함수 범위란 이 함수에 속한 모든 변수를 전체 함수의 범위 내에서 사용하고 재사용할 수 있다는 뜻인데 누구나 다 아는 정의인데 함수 범위란 무엇인가? 그것을 위해? 다음으로 함수 범위의 초를 살펴보겠습니다.

Hide 내부 구현

Hide 내부 구현은 숨김 목적을 달성하기 위해 변수와 함수를 함수 범위로 감싸는 것입니다. 소프트웨어 설계에는 모듈이나 객체의 API 설계와 같이 필요한 내용을 최소한으로 노출시키고 다른 내용은 숨기는 최소 노출의 원칙이라는 매우 유명한 원칙이 있습니다. 최소 노출 원칙을 달성하고 직접적인 외부 액세스를 방지하려면 함수 범위를 사용하여 변수와 함수를 래핑하세요. 다음 예를 살펴보세요.

function doSomething(a) {
  b = a + doSomethingElse( a * 2 );
  console.log( b * 3 );
}
  
function doSomethingElse(a) {
  return a - 1;
}
var b;
doSomething( 2 ); // 15”

이 코드에서 doSomethingElse 및 b는 doSomething 내에서 비공개여야 하지만 노출됩니다. 이는 예상치 못한 형태로 사용되어 예상치 못한 결과를 낳게 됩니다. doSomething 내부에 이러한 비공개 콘텐츠를 숨기는 것이 더 합리적인 설계입니다. 예:

function doSomething(a) {
  function doSomethingElse(a) {
    return a - 1;
  }
  var b;
  b = a + doSomethingElse( a * 2 );
  console.log( b * 3 );
}
doSomething( 2 );

이런 방식으로 b나 doSomethingElse는 doSomething 외부에서 액세스할 수 없습니다. 첫째, doSomething 함수가 전역 범위에 선언되어 전역 함수를 오염시키고, 둘째, 명시적인 호출을 통해 실행해야 하므로 범위를 오염시키지 않고 필요하지 않은 방법이 있습니까? 호출이 자체적으로 실행될 수 있나요? 답은 함수 표현식입니다. 다음 예를 보세요.

(function doSomething(a) {
  function doSomethingElse(a) {
    return a - 1;
  }
  var b;
  b = a + doSomethingElse( a * 2 );
  console.log( b * 3 );
})(2)

먼저 함수 표현식인 (function doSomething(){})을 살펴보세요. 함수 선언과 달리 괄호로 묶인 다음 (function doSomething( a){})() 자체 실행이 가능하고 범위를 오염시키지 않도록 값으로 호출합니다. 커뮤니티에서는 이 사용법에 대해 IIFE라는 용어를 정의했습니다. 이는 함수 표현식의 즉시 실행을 의미합니다

块作用域

除JavaScript外很多编程语言都支持块作用域,尽管你可能写过很伪块作用域形式的代码,最常见的就是for循环:

for(var i=0; i<10; i++) {
  console.log(i)
}

写这段代码通常是希望变量i在循环内部使用,但是实际上i会被绑定到外部作用域中,要确保没有在作用域的其他地方意外使用i,就只能依靠自觉,这时候块级作用域就显得尤为有用,ES6改变了现状,引入了新的let、const关键字,let关键字可以将变量绑定到所在的任意作用域中,也就是let为其声明的变量隐式地创建了作用域:

for(let i=0; i<10; i++) {
  console.log(i)        
}
console.log(i) // ReferenceError

这时候i就只会在for循环的内部有效


위 내용은 JavaScript의 범위에 대한 자세한 소개(코드 예)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제