>웹 프론트엔드 >JS 튜토리얼 >JavaScript_Basics의 범위 및 컨텍스트 사용법에 대한 간략한 개요

JavaScript_Basics의 범위 및 컨텍스트 사용법에 대한 간략한 개요

WBOY
WBOY원래의
2016-05-16 17:10:27821검색

JavaScript의 범위와 컨텍스트는 부분적으로 유연성을 제공하므로 언어마다 고유합니다. 각 함수에는 서로 다른 변수 컨텍스트와 범위가 있습니다. 이러한 개념은 JavaScript의 강력한 디자인 패턴의 기초가 됩니다. 그러나 이는 개발자들에게 큰 혼란을 가져오기도 합니다. 다음은 JavaScript의 컨텍스트와 범위의 차이점과 다양한 디자인 패턴이 이를 사용하는 방법을 포괄적으로 보여줍니다.

컨텍스트 vs 범위

먼저 명확히 해야 할 것은 컨텍스트와 범위는 서로 다른 개념이라는 점입니다. 수년에 걸쳐 나는 많은 개발자들이 종종 이 두 용어를 혼동하여 하나를 다른 것으로 잘못 설명하는 것을 발견했습니다. 공평하게 말하자면, 이 용어들은 매우 혼란스러워졌습니다.

각 함수 호출에는 이와 관련된 범위와 컨텍스트가 있습니다. 기본적으로 범위는 함수 기반이고 컨텍스트는 개체 기반입니다. 즉, 범위는 각 함수 호출의 변수 액세스와 관련되며 각 호출은 독립적입니다. 컨텍스트는 항상 현재 실행 코드를 호출하는 개체에 대한 참조인 this 키워드의 값입니다.

변수 범위

변수는 로컬 또는 전역 범위에서 정의될 수 있으며, 이로 인해 다양한 범위에서 런타임 변수에 액세스할 수 있습니다. 전역 변수는 함수 본문 외부에서 선언되어야 하고, 실행 중인 프로세스 전체에 존재해야 하며, 모든 범위에서 액세스하고 수정할 수 있습니다. 지역 변수는 함수 본문 내에서만 정의되며 각 함수 호출마다 다른 범위를 갖습니다. 이번 주제는 호출 내에서만 값을 할당, 평가, 연산하며, 범위 밖의 값에는 접근할 수 없습니다.

현재 JavaScript는 블록 수준 범위를 지원하지 않습니다. 블록 수준 범위는 if 문, switch 문, 루프 문 등과 같은 문 블록에서 변수를 정의하는 것을 의미합니다. 이는 문 외부에서 변수에 액세스할 수 없음을 의미합니다. 차단하다. 현재 명령문 블록 내에 정의된 모든 변수는 명령문 블록 외부에서 액세스할 수 있습니다. 그러나 let 키워드가 ES6 사양에 공식적으로 추가되었으므로 이는 곧 변경될 것입니다. 지역 변수를 블록 수준 범위로 선언하려면 var 키워드 대신 이를 사용하세요.

"this" 컨텍스트

컨텍스트는 일반적으로 함수가 호출되는 방식에 따라 달라집니다. 함수가 객체의 메소드로 호출되면 메소드가 호출되는 객체로 설정됩니다.

코드 복사 코드는 다음과 같습니다.

var object = {
foo: function(){
alert(this === object)
}
};

object.foo(); // true

new 연산자를 통해 객체의 인스턴스를 생성하는 함수를 호출할 때도 동일한 원칙이 적용됩니다. 이런 방식으로 호출하면 this 값이 새로 생성된 인스턴스로 설정됩니다.
코드 복사 코드는 다음과 같습니다.

function foo(){
alert(this)
}

foo() // 창
new foo() // foo

바인딩되지 않은 함수를 호출하면 기본적으로 전역 컨텍스트 또는 창 개체(브라우저의 경우)로 설정됩니다. 그러나 함수가 엄격 모드("use strict")에서 실행되는 경우 이 값은 기본적으로 정의되지 않음으로 설정됩니다.
실행 컨텍스트 및 범위 체인

Javascript는 단일 스레드 언어이므로 브라우저에서 동시에 한 가지 작업만 수행할 수 있습니다. JavaScript 인터프리터가 처음으로 코드를 실행하면 먼저 전역 컨텍스트가 기본값으로 설정됩니다. 함수가 호출될 때마다 새로운 실행 컨텍스트가 생성됩니다.

여기서 "실행 컨텍스트"라는 용어는 위에서 설명한 컨텍스트가 아니라 범위를 의미하는 경우가 많습니다. 잘못된 이름이지만 이 용어는 ECMAScript 사양에 의해 정의되어 있으므로 이를 준수할 수밖에 없습니다.

새로운 실행 컨텍스트가 생성될 때마다 범위 체인의 최상위에 추가되고 실행 또는 호출 스택이 됩니다. 브라우저는 항상 범위 체인의 맨 위에 있는 현재 실행 컨텍스트에서 실행됩니다. 완료되면 해당 항목(현재 실행 컨텍스트)이 스택 상단에서 제거되고 제어권이 이전 실행 컨텍스트로 반환됩니다. 예:
코드 복사 코드는 다음과 같습니다.

function first(){
두 번째( );
함수 두 번째(){
세 번째();
함수 세 번째(){
네 번째()
함수 네 번째(){
// 뭔가
}
}
}
}
첫 번째()

이전 코드를 실행하면 네 번째 함수까지 중첩된 함수가 위에서 아래로 실행됩니다. 이때 위에서 아래로의 범위 체인은 네 번째, 세 번째, 두 번째, 첫 번째, 전역입니다. 네 번째 함수는 자체 변수와 마찬가지로 전역 변수와 첫 번째, 두 번째, 세 번째 함수에 정의된 모든 변수에 액세스할 수 있습니다. 네 번째 함수의 실행이 완료되면 네 번째 컨텍스트가 범위 체인의 상단에서 제거되고 세 번째 함수로 실행이 반환됩니다. 이 프로세스는 모든 코드 실행이 완료될 때까지 계속됩니다.

다양한 실행 컨텍스트 간의 변수 이름 지정 충돌은 로컬에서 글로벌로 범위 체인을 확장하여 해결됩니다. 이는 동일한 이름을 가진 지역 변수가 범위 체인에서 더 높은 우선순위를 갖는다는 것을 의미합니다.

간단히 말하면 함수 실행 컨텍스트에서 변수에 액세스하려고 할 때마다 조회 프로세스는 항상 자체 변수 개체에서 시작됩니다. 찾고 있는 변수가 자신의 변수 개체에 없으면 범위 체인을 계속 검색하세요. 범위 체인을 올라가 각 실행 컨텍스트 변수 개체를 검사하여 변수 이름과 일치하는 값을 찾습니다.

코드 복사

코드는 다음과 같습니다. 함수 foo() { var local = '개인 변수'; return function bar(){ return local;
}
}

var getLocalVariable = foo() ;
getLocalVariable() // 개인 변수


가장 인기 있는 클로저 유형 중 하나는 잘 알려진 모듈 패턴입니다. 공개, 비공개 및 특권 멤버를 모의할 수 있습니다.



코드 복사

코드는 다음과 같습니다. var Module = (function(){ var privateProperty = 'foo'; function privateMethod(args){
//뭔가
}

return {

publicProperty: "",

publicMethod: function(args){
//do Something
},

privilegedMethod: function(args) ){
privateMethod(args);
}
}
})();


모듈은 실제로 한 쌍의 괄호를 추가하는 싱글톤과 유사합니다. 프로세서가 해석을 마친 후 즉시 실행하십시오(함수를 즉시 실행하십시오). 클로저 실행 컨텍스트의 사용 가능한 유일한 외부 멤버는 반환된 객체(예: Module.publicMethod)의 공용 메서드와 속성입니다. 그러나 실행 컨텍스트가 보호되고(클로저) 변수와의 상호 작용이 공용 메서드를 통해 이루어지기 때문에 모든 개인 속성과 메서드는 프로그램의 수명 주기 전반에 걸쳐 존재합니다.

또 다른 유형의 클로저를 즉시 호출 함수 표현식 IIFE라고 하는데, 이는 창 컨텍스트에서 자체 호출 익명 함수에 지나지 않습니다.



코드 복사

코드는 다음과 같습니다. 함수(창){ var a = 'foo', b = 'bar';
function private(){
// 뭔가를 하세요
}

window.Module = {

public: function(){
// 뭔가를 하세요
}
}

})(this)


전역 네임스페이스, 이 표현식은 매우 유용합니다. 함수 본문 내에서 선언된 모든 변수는 지역 변수이며 클로저를 통해 전체 런타임 환경에서 지속됩니다. 소스 코드를 캡슐화하는 이러한 방식은 프로그램과 프레임워크 모두에 매우 널리 사용되며 일반적으로 외부 세계와 상호 작용하기 위해 단일 전역 인터페이스를 노출합니다.


호출 및 적용

은 함수가 사용자 정의 컨텍스트에서 실행될 수 있도록 모든 함수에 내장된 두 가지 간단한 방법입니다. 호출 함수에는 매개변수 목록이 필요하며 적용 함수를 사용하면 매개변수를 배열로 전달할 수 있습니다.


코드 복사

코드 함수 user(이름, 성, 나이){ // do Something } user.call(window, 'John', 'Doe' , 30);
user.apply(창, ['John', 'Doe', 30])


실행 결과는 동일하며, 윈도우 컨텍스트에서 사용자 함수가 호출되고 동일한 3개의 매개변수가 제공됩니다.

ECMAScript 5(ES5)는 컨텍스트를 제어하기 위해 Function.prototype.bind 메서드를 도입했습니다. 이 함수(컨텍스트)는 바인딩 메서드의 첫 번째 매개 변수에 영구적으로 바인딩됩니다. 함수 호출 방법. 클로저를 통해 함수의 컨텍스트를 수정합니다. 다음은 지원되지 않는 브라우저에 대한 해결 방법입니다.
코드 복사 코드는 다음과 같습니다. 다음:

if(!(Function.prototype의 'bind')){
Function.prototype.bind = function(){
var fn = this, context = 인수[ 0] , args = Array.prototype.slice.call(arguments, 1);
return function(){
return fn.apply(context, args)
}
}
}

컨텍스트 손실(객체 지향 및 이벤트 처리)에 일반적으로 사용됩니다. 이는 노드의 addEventListener 메소드가 항상 이벤트 핸들러가 바인딩되는 노드로서 함수 실행의 컨텍스트를 유지하기 때문에 필요하며, 이는 중요합니다. 그러나 고급 객체 지향 기술을 사용하고 콜백 함수의 컨텍스트를 메서드의 인스턴스로 유지해야 하는 경우 컨텍스트를 수동으로 조정해야 합니다. 바인드가 가져다주는 편리함:
코드 복사 코드는 다음과 같습니다.

함수 MyClass() {
this.element = document.createElement('div');
this.element.addEventListener('click', this.onClick.bind(this), false)
}; 🎜>
MyClass.prototype.onClick = function(e){
// do Something
}

바인드 함수의 소스 코드를 다시 보면 다음 줄은 배열 메서드를 호출하는 비교적 간단한 코드입니다.

코드 복사 코드는 다음과 같습니다.
Array.prototype.slice.call(arguments, 1);

흥미롭게도 인수 객체는 실제로 배열이 아니라는 점에 유의하는 것이 중요합니다. nodelist(document.getElementsByTagName() 메소드)에 의해 반환된 결과인 배열과 유사한 ) 객체로 설명되는 경우가 많습니다. 길이 속성을 포함하고 값을 인덱싱할 수 있지만 슬라이스 및 푸시와 같은 기본 배열 방법을 지원하지 않기 때문에 여전히 배열이 아닙니다. 그러나 배열과 유사하게 동작하므로 배열 메서드를 호출하여 하이재킹할 수 있습니다. 배열과 유사한 컨텍스트에서 배열 메서드를 실행하려면 위의 예를 따르세요.

다른 객체 메소드를 호출하는 이 기술은 JavaScript에서 고전적인 상속(클래스 상속)을 에뮬레이션할 때 객체 지향에도 적용됩니다.

코드 복사 코드는 다음과 같습니다.
MyClass.prototype.init = function(){
// "MyClass" 컨텍스트에서 슈퍼클래스 init 메소드를 호출합니다. " 인스턴스
MySuperClass.prototype.init.apply(this, 인수);
}

하위 클래스(MyClass)의 인스턴스에서 슈퍼 클래스(MySuperClass)의 메소드를 호출하여 , 우리는 이 강력한 디자인 패턴을 재현할 수 있습니다.


결론
범위와 컨텍스트가 현대 자바스크립트 역할에서 중요하고 기본적인 역할을 하기 때문에 고급 디자인 패턴을 배우기 전에 이러한 개념을 이해하는 것이 매우 중요합니다. 클로저, 객체 지향, 상속 또는 다양한 기본 구현에 관해 이야기할 때 컨텍스트와 범위가 중요한 역할을 합니다. 목표가 JavaScript 언어를 마스터하고 해당 구성 요소를 깊이 이해하는 것이라면 범위와 컨텍스트가 출발점이 되어야 합니다.


번역가의 보충 자료
작성자가 구현한 바인드 함수가 불완전합니다. 바인드에서 반환된 함수를 호출할 때 매개변수를 전달할 수 없습니다. 🎜>


if(!('bind' Function.prototype)){
Function.prototype.bind = function(){
var fn = this, context = 인수[0], args = Array.prototype.slice.call(arguments, 1);
return function(){
return fn.apply(context, args.concat(arguments));//fixed
}
}
}

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.