>  기사  >  웹 프론트엔드  >  Javascript 함수, 재귀 및 클로저(실행 환경, 변수 객체 및 범위 체인) 사용에 대한 자세한 설명_기본 지식

Javascript 함수, 재귀 및 클로저(실행 환경, 변수 객체 및 범위 체인) 사용에 대한 자세한 설명_기본 지식

WBOY
WBOY원래의
2016-05-16 17:34:15891검색

함수 표현

1. JavaScript에서 함수를 정의하는 방법에는 두 가지가 있습니다.

 1-1. 함수 선언:

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

function funcName(arg1,arg2,arg3){
//함수 본문
}

 ①name 속성: 함수 이름을 읽을 수 있습니다. 비표준 브라우저 지원: FF, Chrome, Safari, Opera.
 ②함수 선언 승격: 코드를 실행하기 전에 함수 선언을 읽는다는 의미입니다. 즉, 함수 호출은 함수 선언 앞에 배치될 수 있습니다.

 1-2. 함수 표현:

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

var funcName = function(arg1,arg2,arg3){
//함수 본문
};

  ①익명 함수(익명 함수 또는 람다 함수) : function 키워드 뒤에는 식별자가 없으며 name 속성 값은 빈 문자열입니다. 함수가 값으로 사용될 때마다 익명 함수를 사용할 수 있습니다.
 ②다른 표현식과 마찬가지로 함수 표현식은 사용하기 전에 값을 할당해야 하므로 "함수 선언 승격"과 같은 효과는 없습니다.
  ③ECMAScript의 잘못된 함수 구문:
코드 복사 코드는 다음과 같습니다.

if 판단 에 중복된 함수 선언

if(조건){
function sayHi(){
Alert("안녕하세요!");
}
} else {
function sayHi(){
Alert( "Yo!");
}
}


브라우저 JavaScript 엔진은 오류 차이를 수정합니다. 대부분의 브라우저는 조건을 무시하고 두 번째 문을 반환합니다. 조건은 true인 경우 첫 번째 명령문을 반환합니다.
함수 표현식을 사용하여 해결 및 구현:
코드 복사 코드는 다음과 같습니다.

판단 함수 표현의 경우

var sayHi;
if(조건){
sayHi = function(){
Alert("안녕하세요!");
}
} else {
sayHi = 함수 (){
Alert("Yo!");
}
}


2. 재귀
재귀함수가 형성된 함수 자신의 이름을 부르면서.
코드 복사 코드는 다음과 같습니다.

함수 팩토리얼(num){ //A 고전적인 재귀 계승 함수
if (num <= 1){
return 1;
} else {
return num *factorial(num-1);
}
}

  ①다음 코드를 사용하여 이 함수를 호출하면 오류가 발생합니다.
코드 복사 코드는 다음과 같습니다.

var anotherFactory =factorial;
factorial = null;
alert(anotherFactorial(4));

저장 후 팩토리얼() 함수를 anotherFactory 변수에 넣고, 팩토리얼 변수를 null로 설정한 후에는 더 이상 해당 함수를 참조하지 않으며, anotherFactorial(4)에서 팩토리얼() 함수를 실행해야 하므로 오류가 발생합니다.
  인수.callee(실행 중인 함수에 대한 포인터)를 사용하여 해결합니다.
코드 복사 코드는 다음과 같습니다.

솔루션

함수 계승(숫자){
if (num <= 1){
return 1;
} else {
return num *args.callee(num-1);
}
}

var anotherFactorial = Factorial;
factorial = null;
alert(anotherFactorial(4)) //24


Non-Strict 모드에서는 재귀 함수를 사용할 때 함수 이름 대신 Argument.callee를 사용하는 것이 더 안전합니다.
Strict 모드에서는 Argument.callee를 사용할 때 오류가 발생합니다. 함수 선언 대신:
코드 복사 코드는 다음과 같습니다.

함수 표현식이 함수를 대체합니다. 선언

var 계승 = 함수 f(num){
if (num <= 1){
return 1;
} else {
return num * f(num-1);
}
}


4. 폐쇄

은 다른 함수의 범위에 있는 변수에 접근할 수 있는 함수를 나타냅니다. (일반적인 형태는 함수 중첩입니다)

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

함수 wai(pro ){
return function(obj1,obj2){
var val1 = obj1[pro];
var val2 = obj2[pro];
if(val1 return - 🎜>}


익명 함수를 반환할 때 익명 함수의 범위 체인은 함수의 활성 객체와 전역 변수 객체를 포함하도록 초기화됩니다. 즉, 익명 함수에는 wai() 함수의 범위가 포함됩니다.
각 함수가 호출되면 실행 환경, 변수 객체 및 해당 범위 체인이 생성됩니다.


4-1. 실행환경 및 범위

환경이라고 불리는 실행 환경 실행 컨텍스트는 함수가 액세스할 수 있는 변수 및 기타 데이터를 정의하고 각각의 동작을 결정합니다.
 ①각 실행 환경에는 환경에서 정의한 모든 변수와 함수를 저장하는 변수 객체가 있습니다. 이 개체는 코드에서 액세스할 수 없지만 파서는 데이터를 처리할 때 뒤에서 이를 사용합니다.

  전역 변수 객체는 가장 주변적인 실행 환경입니다. 웹 브라우저에서는 윈도우 객체로 간주되므로 모든 전역 객체와 함수는 윈도우 객체의 속성과 메서드에 의해 생성됩니다.

실행환경 내의 코드가 실행된 후 환경은 소멸되며, 그 안에 저장된 변수 및 함수 정의도 소멸됩니다.  ②환경에서 코드가 실행되면 실행 환경이 접근하는 모든 변수와 함수에 순차적으로 접근할 수 있도록 변수 객체의 스코프 체인이 생성됩니다.

  스코프 체인의 앞단은 항상 현재 실행되는 코드가 위치한 환경의 변수 객체입니다. 환경이 함수인 경우 활성 개체가 변수 개체로 사용됩니다.

  활성 개체에는 처음에 인수 개체라는 하나의 변수만 포함됩니다.
 범위 체인의 다음 변수 개체는 포함 환경에서 오고, 다음 변수 개체는 전역 실행 환경으로 계속될 때까지 다음 포함 환경에서 옵니다.

③식별자 구문 분석: 이전 단락부터 시작하여 범위 체인을 따라 수준별로 식별자를 검색하는 프로세스입니다. 【찾을 수 없으면 보통 오류가 발생합니다】


4-2.함수 생성 및 실행 시:

코드 복사

함수 비교(val1,val2){ if(val1 return -1; }else if(val1>val2){ 반환 1;
}else{
반환 0;
};
}
var 결과 = 비교(5, 10);


 ① Compare() 함수를 생성할 때 전역 변수 개체를 미리 포함하는 범위 체인이 생성되어 내부 [[scope]] 속성에 저장됩니다.
 ②로컬 함수 Compare()의 변수 객체는 함수 실행 중에만 존재합니다.
함수가 호출되면 실행 환경이 생성되고, 함수의 [[scope]] 속성에 객체를 복사하여 실행 환경의 스코프 체인이 구축됩니다.
  ③ Compare()와 같은 함수가 처음 호출되면 이를 포함하는 활성 개체, 인수, val1 및 val2가 생성됩니다.
 4전역 실행 환경의 변수 개체(이것, 결과 및 비교 포함)는 Compare() 실행 환경의 범위 체인에서 두 번째입니다.
 ⑤스코프 체인은 본질적으로 변수 객체를 가리키는 포인터 목록으로, 참조만 할 뿐 실제로는 변수 객체를 포함하지 않습니다.
 ⑥ 함수에서 변수에 접근할 때마다 해당 이름의 변수가 스코프 체인에서 검색됩니다.

4-3. 클로저의 범위 체인

다른 함수 내에 정의된 함수는 해당 함수를 포함하는 활성 개체를 해당 범위 체인에 추가합니다.
 ① 함수 객체를 null에 할당하는 것은 가비지 수집 루틴에 이를 지우라고 알리는 것과 같습니다. 함수 범위 체인이 파괴됨에 따라 해당 범위 체인(전역 범위 제외)도 안전하게 파괴됩니다.
 ②클로저는 포함하는 기능의 범위를 전달하기 때문에 다른 기능보다 더 많은 메모리를 차지합니다.

4-4. 클로저와 변수

범위 연결의 부작용: 클로저는 포함하는 함수에 있는 모든 변수의 마지막 값만 얻을 수 있습니다.

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

function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i ){
result[i] = function(){
return i;
};
}
결과 반환;
}

①createFunctions() 함수, 결과 배열에 10개의 클로저를 할당한 후 결과 배열을 반환합니다. 각 클로저는 자체 인덱스를 반환하지만 실제로는 모두 10을 반환합니다.
createFunctions() 함수의 활성 객체는 각 함수(클로저)의 범위 체인에 저장되므로 동일한 변수 i를 참조합니다. createFunctions 함수가 실행될 때 i의 값은 10이므로 클로저 i's in the bag도 모두 10개입니다.
 ②해결책은 클로저를 사용하지 않고 익명 함수를 만들고 해당 매개변수에 i 값을 할당하는 것입니다.
코드 복사 코드는 다음과 같습니다:

function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i ){
result[i] = function(num){
  🎜> }


루프할 때마다 한 번씩 실행되는 익명 함수를 만듭니다. 매번 함수를 둘러싸는 i 값을 사용합니다. 매개변수로 반복하여 익명 함수에 저장합니다. 함수 매개변수는 참조가 아닌 값으로 전달되기 때문에 각 익명 함수의 num 값은 루프를 통과할 때마다 i 값의 복사본입니다.


4-5.이 개체

이 개체는 함수의 실행 환경에 따라 런타임에 바인딩됩니다.  글로벌 함수에서는 window와 동일하며 객체에 의해 함수가 호출될 때는 이것이 객체입니다.

익명 함수의 실행 환경은 전역적이며 일반적으로 this 개체는 창을 참조합니다. call()이나 apply()를 통해 함수 실행 환경을 변경할 때 this는 해당 객체를 가리킨다.  ①각 함수가 호출되면 자동으로 두 개의 특수 변수인 this와 인수를 얻습니다. 내부 함수가 이 두 변수를 검색할 때 만료된 활성 개체까지만 검색하며 외부 함수의 이 두 변수에는 절대 액세스할 수 없습니다. 그러나 이 객체를 클로저가 접근할 수 있는 변수의 외부 범위에 저장함으로써 클로저가 객체에 접근할 수 있습니다.




코드 복사

코드는 다음과 같습니다.

클로저는 외부 함수의 this 객체에 액세스합니다

var name = "창";

var object = {
name : "내 개체",

getNameFunc: function(){
var that = this;
return function(){
return that.name;
};
}
};

alert(object.getNameFunc()()); //"MyObject"


  함수를 둘러싼 인수 객체도 이 메서드를 통해 클로저로 액세스할 수 있습니다.

5. 함수 선언을 함수 표현식으로 변환

자바스크립트는 함수 선언 시작 부분에 function 키워드를 넣는데, 함수 선언 뒤에 괄호가 올 수 없으므로 function(){......}(); 오류가 발생합니다.
함수 선언을 함수 표현식으로 변환하려면 함수 선언에 괄호 쌍을 추가하세요.

코드 복사 코드 다음과 같습니다:

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