각 프로그래밍 언어에서 변수에는 특정 유효한 범위가 있습니다. 이 범위를 초과하면 변수가 유효하지 않습니다. 이것은 변수의 범위입니다. 수학적 관점에서 볼 때 독립 변수의 영역입니다.
범위는 접근 가능한 변수 범위, 즉 스코프 변수 및 함수의 가시성 및 수명주기를 제어합니다. JavaScript에서 객체와 함수는 또한 변수이며 변수는 기능 본문과 중첩 된 임의의 기능 본체에 의해 중첩 된 임의의 기능 본체 내부에서 정의됩니다.
1. 정적 범위와 동적 범위
정적 범위
이는 선언의 범위가 어휘 스코프라고도하는 프로그램 본문을 기반으로 컴파일 시간에 결정됨을 의미합니다. 대부분의 최신 프로그래밍 언어는 정적 범위 규칙을 채택하고 JavaScript는이 범위를 채택합니다.
정적 스코프를 사용하는 언어에서 가장 내면의 중첩 범위 규칙은 기본적으로 다음과 같습니다. 선언에 의해 소개 된 식별자는 선언이 위치한 스코프에서 볼 수 있으며 내부에있는 동일한 이름 식별자의 다른 선언으로 덮여 있지 않는 한 내부에 중첩 된 각 범위에서 볼 수 있습니다.
주어진 식별자가 참조하는 객체를 찾으려면 현재 가장 안쪽 범위에서 찾아야합니다. 선언이 발견되면 식별자가 참조한 객체를 찾을 수 있습니다. 그렇지 않으면, 우리는 직접 외부 범위로 검색하고 프로그램의 가장 바깥 쪽 둥지 레벨, 즉 글로벌 객체 선언이 위치한 범위에 도달 할 때까지 외부로 외부 범위를 계속 점검합니다. 모든 수준에서 선언이 발견되지 않으면 프로그램에 오류가 있습니다. 다음과 같이 :
함수 cha () {var name = "xiao;" 함수 chb () {function chc () {console.log (name); }}}먼저 함수는 chb ()의 이름 정의를 검색 한 다음 레이어별로 레이어를 계속 검색합니다. 마지막으로 이름의 정의는 cha ()에서 찾을 수 있습니다. 발견되지 않으면 오류 가보고됩니다.
2. 동적 범위
동적으로 스코핑 된 언어에서, 프로그램의 변수에 의해 참조 된 객체는 프로그램이 실행되는 순간에 프로그램의 제어 흐름 정보를 기반으로 결정됩니다.
2. JavaScript의 범위
JavaScript에는 두 가지 스코프, 즉 글로벌 범위와 로컬 범위가 있습니다.
1. 글로벌 범위
코드의 어느 곳에도 정의가 있습니다. 전역 변수가 HTML 페이지에 중첩 된 JS 코드에 정의 되더라도 참조 된 JS 파일에서 변수에 여전히 액세스 할 수 있습니다. 이것은 글로벌 변수에 오염을 일으킬 가능성이 매우 높습니다.
다음 세 가지 사례의 변수는 글로벌 변수로 간주됩니다.
(1) 가장 바깥 함수와 가장 바깥 변수는 전역 범위를 갖습니다.
(2) 정의없이 직접 할당 된 변수는 자동으로 전역 범위를 갖도록 선언됩니다.
(3) 모든 창 객체의 속성에는 전역 범위가 있습니다.
2. 로컬 범위
로컬 스코프는 일반적으로 내부 함수 (함수 범위)와 같은 고정 코드 스 니펫에서만 액세스 할 수 있습니다.
var name = "xuxiaoping"; function echoname () {var firstname = "xu"; // local scope secondname = "xiao"; // global scope function echofirstname () {console.log (First Name); // xu} console.log (secondName); return echofirstname;} console.log (name); // global scope var f = echoname (); f (); console.log (FirstName); console.log (SecondName);결과는 다음과 같습니다.
xuxiaoping
Xiao
xu // 내부 함수는 외부 기능의 변수에 액세스 할 수 있습니다
undenfined // 함수의 내부 변수는 함수 외부에 액세스 할 수 없습니다.
Xiao
JavaScript는 글로벌 변수를 창 객체에 첨부하고 창 객체의 속성이됩니다.
3. 함수 범위
블록 레벨 범위 : 브레이스의 모든 명령문 세트는 블록에 속하며, 이에 정의 된 모든 변수는 코드 블록 외부에서 보이지 않습니다. 대부분의 C 클래스 언어에는 블록 수준의 스코프가 있습니다.
그러나 JavaScript의 중요한 기능은 블록 레벨 범위가 없다는 것입니다.
함수 echoi () {for (var i = 0; i <10; i ++) {; // console.log (i); } if (true) {var str = "hello"; } console.log (i); console.log (str);} echoi ();출력 결과는 다음과 같습니다.
10
안녕하세요
for 문 외부 (또는 경우) 외부에서 블록에 정의한 변수에 여전히 액세스 할 수 있음을 알 수 있습니다. 즉, JavaScript는 블록 레벨 스코프를 지원하지 않으며 기능 스코프 만 지원하며 함수의 어느 곳에서나 정의 된 변수는 해당 기능의 어느 곳에서나 볼 수 있습니다. 처음부터 C와 Java를 배우는 사람으로서, 이것은 적응하기가 약간 어렵습니다. 내 테스트에 따르면 PHP에 대해서도 마찬가지입니다.
물론 JavaScript의 클로저 특성을 사용하여 블록 레벨 범위를 시뮬레이션 할 수 있습니다.
함수 echoi () {(function () {for (var i = 0; i <10; i ++) {; // console.log (i);}}) (); if (true) {var str = "hello"; } console.log (i); console.log (str);} echoi ();결과는 다음과 같습니다. 정의되지 않았습니다
이것은 변수의 정의를 분리합니다. JS에서는 명명 충돌을 방지하기 위해 글로벌 변수와 글로벌 기능을 가능한 한 많이 피해야하므로 이러한 종류의 폐쇄는 여러 가지 방법으로 사용됩니다.
4. JavaScript 변수 수명주기
JavaScript 변수 수명주기는 선언 될 때 초기화됩니다.
함수가 실행 된 후 로컬 변수가 파괴됩니다.
페이지가 닫힌 후 글로벌 변수가 파괴됩니다.
3. JavaScrip 스코프 체인
체인처럼 보이며 데이터 구조의 링크 된 목록과 결합 할 수 있습니다.
JavaScript에서는 기능이 객체이지만 실제로 JavaScript의 모든 것은 객체입니다. 다른 객체와 마찬가지로 기능 객체에는 코드를 통해 액세스 할 수있는 속성과 JavaScript 엔진에만 액세스 할 수있는 일련의 내부 속성이 있습니다. 내부 속성 중 하나는 ECMA-262 표준의 세 번째 판에 의해 정의 된 [[Scope]]입니다. 이 내부 속성에는 함수에 의해 생성 된 범위의 객체 모음이 포함되어 있습니다. 이 컬렉션을 기능 범위 체인이라고하며 함수로 액세스 할 수있는 데이터를 결정합니다.
함수가 생성되면 스코프 체인에는 기능 범위에서 액세스 할 수있는 데이터 객체가 채워집니다. 예를 들어 다음과 같은 기능을 정의하십시오.
함수 추가 (num1, num2) {var sum = num1 + num2; 반환 합계;}함수 ADD가 생성되면 아래 그림과 같이 모든 전역 변수를 포함하는 전역 객체가 채워집니다 (참고 : 그림은 모든 변수 중 일부 만 제공합니다).
기능 추가 범위는 실행 중에 사용됩니다. 예를 들어 다음 코드를 실행하십시오.
var total = 추가 (5,10);
이 함수를 실행할 때 "실행 컨텍스트"라는 내부 객체가 생성됩니다. 런타임 컨텍스트는 함수가 실행되는 환경을 정의합니다. 각 런타임 컨텍스트에는 식별자 구문 분석을위한 자체 스코프 체인이 있습니다. 런타임 컨텍스트가 만들어지면 스코프 체인은 현재 실행중인 함수의 [[Scope]]에 포함 된 객체로 초기화됩니다.
이 값은 함수에 나타나는 순서대로 런타임 컨텍스트의 범위 체인으로 복사됩니다. 함께 함께 "Activation Object"라는 새로운 객체를 형성하는데, 여기에는 모든 로컬 변수, 매개 변수, 매개 변수 세트 및이 기능이 포함되어 있습니다. 그러면이 객체는 스코프 체인의 프론트 엔드로 밀려납니다. 런닝 컨텍스트가 파괴되면 활성 물체가 파괴됩니다. 새로운 스코프 체인은 아래 그림에 나와 있습니다.
기능 실행 중에 변수가 발생할 때마다 식별자 구문 분석 프로세스가 전달되어 데이터를 얻고 저장할 위치를 결정합니다. 이 프로세스는 스코프 체인의 헤드에서 시작됩니다. 즉, 활성 객체에서 동일한 이름의 식별자를 검색합니다. 발견되면이 식별자에 해당하는 변수를 사용하십시오. 발견되지 않으면 스코프 체인에서 다음 객체를 계속 검색하십시오. 검색 후 모든 객체를 찾을 수없는 경우 식별자는 정의되지 않은 것으로 간주됩니다. 함수 실행 중에 각 식별자는 이러한 검색 프로세스를 거쳐야합니다.
4. 스코프 체인 및 코드 최적화
스코프 체인의 구조에서 런타임 컨텍스트의 스코프 체인에서 식별자가 더 깊을수록 읽기 및 쓰기 속도가 느려집니다. 위 그림과 같이, 런타임 동안 컨텍스트 범위 체인의 끝에 항상 글로벌 변수가 존재하기 때문에 식별자를 구문 분석 할 때 글로벌 변수를 찾는 것이 가장 느립니다. 따라서 코드를 작성할 때는 가능한 한 적은 글로벌 변수를 사용하고 가능한 한 로컬 변수를 사용해야합니다. 좋은 규칙은 다음과 같습니다. 크로스 커프 객체가 두 번 이상 참조되는 경우 사용하기 전에 로컬 변수에 저장하십시오. 예를 들어 다음 코드 :
function changeColor () {document.getElementById ( "btnchange"). onclick = function () {document.getElementById ( "targetCanvas"). Style.backgroundColor = "red"; };}이 기능은 글로벌 변수 문서를 두 번 말합니다. 변수는 전체 스코프 체인을 통해 전역 객체에서 마지막으로 발견 될 때까지 검색해야합니다. 이 코드는 다음과 같이 다시 작성할 수 있습니다.
함수 changecolor () {var doc = document; doc.getElementById ( "btnchange"). onclick = function () {doc.getElementById ( "targetCanvas"). Style.backgroundColor = "red"; };}이 코드는 상대적으로 간단하며 다시 쓰기 후에 성능이 크게 향상되지는 않지만 프로그램의 많은 글로벌 변수에 반복적으로 액세스하면 다시 쓰기 후 코드의 성능이 크게 향상됩니다.
5. 변화 범위 체인
해당 런타임 컨텍스트는 숫자가 실행될 때마다 고유하므로 동일한 기능을 여러 번 호출하면 여러 런타임 컨텍스트가 생성됩니다. 함수가 실행되면 실행 컨텍스트가 파괴됩니다. 각 런타임 컨텍스트는 스코프 체인과 관련이 있습니다. 일반적으로, 실행중인 컨텍스트 동안, 스코프 체인은 with 문과 캐치 문에 의해서만 영향을받습니다.
with 문은 중복 코드를 쓰지 않기 위해 객체를 적용하는 빠른 방법입니다. 예를 들어:
함수 initUi () {with (document) {var bd = body, links = getElementsByTagName ( "a"), i = 0, len = links.length; while (i <len) {update (링크 [i ++]); } getElementById ( "btninit"). onclick = function () {dosomething (); }; }}여기에서 너비 진술을 사용하여 문서를 여러 번 쓰지 않으면 더 효율적으로 보이지만 실제로 성능 문제가 발생합니다.
코드가 with 문으로 실행되면 런타임 컨텍스트의 스코프 체인이 일시적으로 변경됩니다. 매개 변수에 의해 지정된 객체의 모든 속성이 포함 된 새로운 변이 가능한 객체가 생성됩니다. 이 객체는 범위 체인의 헤드로 밀려 나게됩니다. 즉, 함수의 모든 로컬 변수가 이제 두 번째 스코프 체인 객체에 있으므로 액세스가 더 비쌉니다. 아래 그림과 같이 :
따라서 프로그램에서 진술을 피해야합니다. 이 예에서는 문서를 로컬 변수에 저장하면 성능을 향상시킬 수 있습니다.
요약
1. 변수의 범위는 변수의 범위가 유효한 곳입니다.
2. 변수의 범위 체인은 생성 된 범위의 객체 모음입니다.
위의 내용은이 기사에 관한 모든 것입니다. 모든 사람들이 JavaScript 프로그래밍을 배우는 것이 도움이되기를 바랍니다.