> 웹 프론트엔드 > JS 튜토리얼 > JavaScript 고급 프로그래밍(3판) 학습 노트 7 js 함수(1부)_기본 지식

JavaScript 고급 프로그래밍(3판) 학습 노트 7 js 함수(1부)_기본 지식

WBOY
풀어 주다: 2016-05-16 17:49:10
원래의
939명이 탐색했습니다.
변수 유형

함수에 앞서 변수 유형에 대해 먼저 알아보겠습니다.

1. 변수: 변수는 본질적으로 이름이 지정된 메모리 공간입니다.

2. 변수의 데이터 유형: Number 유형, Boolean 유형, Object 유형 등 변수가 저장할 수 있는 값의 데이터 유형을 나타냅니다. 변수는 동적이며 변수의 데이터 유형을 변경할 때 런타임에 실행될 수 있습니다.

3. 변수 유형: 변수 자체의 유형을 의미합니다. ECMAScript에는 값 유형과 참조 유형의 두 가지 유형만 있습니다. 변수의 데이터 유형이 단순 데이터 유형인 경우 변수 유형은 값 유형입니다. 변수의 데이터 유형이 객체 유형인 경우 변수 유형은 참조 유형입니다. 모호성을 유발하지 않으면서 변수의 데이터 유형을 변수 유형이라고 부를 수도 있습니다.

그렇다면 값 유형과 참조 유형의 차이점은 무엇인가요? 가장 중요한 것은 변수 유형이 값 유형인 경우 변수는 변수 값 자체를 저장하고, 변수 유형이 참조 유형인 경우 변수는 변수 값이 아닌 변수 값에 대한 포인터만 저장한다는 점입니다. 참조에 액세스 해당 유형의 변수 값을 얻으면 포인터를 먼저 얻은 다음 포인터를 기반으로 변수 값을 얻습니다. 참조 유형 변수 값을 다른 변수에 할당하면 결과적으로 두 변수가 동시에 동일한 변수 값을 가리키게 되며 둘 중 하나를 수정하면 다른 변수도 수정됩니다.
코드 복사 코드는 다음과 같습니다.

var a = {
이름:'린지송',
나이:29
};
var b = a;//참조 유형 변수 a를 변수 b에 할당합니다. a와 b는 모두 a가 가리키는 개체를 가리킵니다.
b.name = 'oulinhai';/ /b가 가리키는 객체를 수정합니다. 즉, a가 가리키는 객체가 수정되었습니다.
console.info(a.name) //oulinhai
b = {//변수를 다시 할당합니다. 그러나 b가 가리키는 객체는 변경되지 않았습니다. 즉, a가 가리키는 객체는 변경되지 않았습니다.
name:'hujinxing',
age:23
}
console.info(a.name );//oulinhai

알겠습니다. 먼저 변수 유형에 대해 이야기해 보겠습니다. 데이터 구조를 메모리에 계속 저장하면 가라앉고 뜨지 못할까 봐 걱정됩니다.

함수

객체가 방이라면 함수는 마법효과가 있는 방입니다. 함수는 객체이고, 이 함수 객체에도 마법 같은 함수가 많이 있습니다...

1. 함수

(1) 함수는 객체입니다

Function 객체이기도 하고, 함수 객체 인스턴스를 생성하는데 사용되는 함수는 내장 Function() 함수입니다(객체 인스턴스를 생성하려면 함수가 필요하고, 함수는 객체 인스턴스를 만드는 걸까요? 닭이 알을 낳을 수 있고 알이 닭을 부화시킬 수 있다면, 철학자에게 맡기자) 그러나 기능과 같은 객체는 너무 다릅니다. 함수 객체 인스턴스에서 typeof를 사용할 때 객체 대신 함수를 반환하는 일반 객체에서.

(2) 함수 이름은 함수 객체를 가리키는 참조형 변수입니다

function fn(p){
console.info(p)
}
console.info(fn);//fn(p), fn을 일반 변수로 사용할 수 있습니다.
var b = fn;
b('function');//function에 액세스하려면 b에 대한 함수 호출을 사용하여 b가 가리키는 객체를 나타낼 수 있습니다. 즉, fn)이 가리키는 객체는 함수입니다

참고: 함수 이름과 관련하여 ES5의 엄격 모드에서는 eval과 인수의 사용이 더 이상 허용되지 않습니다. 매개변수 이름에는 사용할 수 없습니다. 전문 해커가 아닌 이상 이를 식별자로 사용하지 않을 것입니다.

2. 함수 생성

(1) 함수는 객체로서 일반 객체와 유사한 방식으로 생성자 Function()을 호출하여 생성됩니다. 이는 임의 개수의 매개변수를 허용할 수 있으며, 마지막 매개변수는 함수 본문으로 사용되며 이전 매개변수는 모두 쉼표로 구분된 하나의 매개변수로 전달될 수도 있습니다. 일반 형식은 다음과 같습니다.
코드 복사 코드는 다음과 같습니다.

var fn = new 함수 (p1, p2, ..., pn, 본문)
//또는
var fn = Function(p1, p2, ..., pn, body); var fn = new Function("p1, p2, ..., pn", q1, q2, ..., qn, body)
//또는
var fn = Function("p1, p2, ..., pn", q1, q2, ..., qn, body);


예:


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

var add = new Function('a','b','return a b;')
console.info(add(2,1));//3
var subtract = Function('a','b','return a - b;');
console.info(subtract(2,1));//1
var sum = new Function('a, b','c','return a b c;');
console.info(sum(1,2,3));//6

이런 방식으로 함수를 생성하면 코드를 두 번(일반 구문 분석을 위해 한 번, 함수 본문을 위해 한 번) 구문 분석하면 효율성에 영향을 주지만 함수 본문을 동적으로 컴파일해야 하는 상황에는 더 적합합니다.

(2) 함수 개체 자체의 특수한 특성으로 인해 function 키워드를 사용하여 함수를 만들 수도 있습니다.
코드 복사 코드는 다음과 같습니다:

function add(a, b){
return a b;
}
console.info(add( 2,1));/ /3
var subtract = function(a, b){
return a - b
}
console.info(subtract(2,1)); //1

위에서 볼 수 있듯이 function 키워드를 사용하여 함수를 만드는 방법에는 함수 선언과 함수 표현식의 두 가지 방법이 있습니다. 두 가지 방법 모두 우리가 원하는 효과를 얻을 수 있는데, 두 방법의 차이점은 무엇입니까? 이것이 우리가 다음에 이야기할 것입니다.

3. 함수 선언 및 함수 표현

(1) 형식적 구분에서 ECMA-262 사양을 보면 다음과 같습니다.
코드 복사 코드는 다음과 같습니다.

함수 선언: 함수 식별자(매개변수 목록(선택)){함수 본문 }
함수식 : 함수식별자(선택) (매개변수목록(선택)) {함수본문}

함수식의 식별자(함수명)를 제외하고는 선택사항이라는 점 외에는 차이가 없습니다. 하지만 이를 통해서도 알 수 있습니다. 함수 이름이 없는 모든 항목은 함수 표현식이어야 합니다. 물론 함수 이름이 있다면 문맥을 통해서만 판단할 수 있습니다.

(2) 문맥과 구별하면 간단합니다. 즉, 표현식만 표시할 수 있는 문맥은 함수 표현식이어야 하고, 명령문만 표시할 수 있는 문맥은 함수 선언이어야 합니다. 몇 가지 예를 들어보세요.
코드 복사 코드는 다음과 같습니다.

function fn(){ };/ /함수 선언
//function fn(){}(); // 예외, 함수 선언을 직접 호출할 수 없습니다.
var fn = function fn(){};//함수 표현식
(function fn (){});//그룹화 연산자
function fn(){console.info(1);}();//1 함수 표현식 내의 함수 표현식은 연산자 뒤에 표시됩니다. , 여기서는 new
new function fn(){console.info(2);}();//2, function 표현식과 같은 다른 연산자를 new 연산자 뒤에 사용할 수도 있습니다.
(function(){
function fn(){};//함수 선언
})

(3) 차이점: 왜 그렇게 많은 노력을 기울이나요? 구별 함수 선언과 함수 표현식은 어떻습니까? 당연히 차이점 때문입니다. 가장 큰 차이점은 선언이 승격된다는 것입니다. 선언 승격에 관해서는 기본 문법에 대한 이전 기사에서 전역 범위의 선언 승격에 대해 논의했습니다.

A. 엔진이 구문 분석할 때 먼저 함수 선언을 구문 분석한 다음 변수 선언을 구문 분석하고(분석 중에 유형을 덮어쓰지 않음) 마지막으로 코드를 실행합니다. .함수 선언을 파싱할 때 타입(함수)을 동시에 파싱하지만, 변수 선언을 파싱할 때는 변수만 파싱하고 초기화하지 않습니다.

시연(기억)할 몇 가지 예도 있지만 동일한 이름을 가진 선언 예가 없습니다.


console.info(typeof fn);//function, 선언 승격, 함수에 따라
var fn = ' ';
function fn(){
}
console.info(typeof fn);//string, 코드가 실행되었으므로 여기서 fn의 유형은 string
try{
fn(); //이미 문자열 유형이므로 호출할 수 없습니다.
}catch(e){
console.info(e);//TypeError
}
fn = function(){ console.info('fn');};//fn을 호출하려면 함수 표현식을 사용하여 fn에 할당해야 합니다.
fn();//fn ,

console.info(typeof gn);//function
function gn(){
}
var gn =
console.info(typeof)를 호출할 수 있습니다. gn);//문자열


변수 선언이 앞이든 뒤이든 상관없이 선언이 승격되면 함수 선언이 우선한다는 것을 알 수 있습니다. 그러나 선언이 승격된 후에는 변수 초기화를 수행해야 하므로 함수 선언이 우선 적용됩니다. 더 이상 초기화되지 않으므로(승격 중에 함수 유형이 구문 분석됨) 나중에 출력할 때 String 유형이 됩니다.

위의 3번째 줄에 함수를 정의한 뒤 7번째 줄에서 바로 호출했는데 작동하지 않네요! 전역 네임스페이스를 깨끗하게 유지하는 것의 중요성을 이해해야 합니다. 그렇지 않으면 "코드에 함수를 명확하게 정의했지만 호출할 수 없습니다."와 같은 문제가 발생할 수 있습니다. 가능하다면 함수 표현식을 사용하여 정의하는 것이 가장 좋습니다. 물론 이렇게 하면 다른 사람의 코드가 손상될 위험이 있습니다.

또 다른 질문이 있습니다. 변수 선언이 승격될 때가 아니라 초기화 중에 변수 유형이 변경되는지 어떻게 알 수 있나요? 아래 코드를 보세요:
코드 복사 코드는 다음과 같습니다:

console. info(typeof fn) ;//function
function fn(){
}
var fn
console.info(typeof fn);//function

보시다시피 The 승격된 유형은 함수이고 초기화 코드가 없으므로 최종 유형은 변경되지 않았습니다.

함수 선언 및 함수 표현식과 관련하여 주의할 점이 하나 더 있습니다.
코드 복사 코드는 다음과 같습니다.

if(true){
function fn(){
return 1
}
}else{
function fn() {
return 2;
}
}
console.info(fn());// Firefox에서 출력 1, Opera에서 출력 2, Opera에서 프로모션 선언, 후속 명령문 동일한 레벨의 이전 선언을 덮어씁니다

if(true){
gn = function(){
return 1
}else{
gn = function() {
return 2;
};
}
console.info(gn());// 1, 모든 브라우저 출력은 1

ECMAScript 사양에서 명명된 함수 표현식의 식별자는 내부 범위에 속하고, 함수 선언의 식별자는 정의 범위에 속합니다.

코드 복사 코드는 다음과 같습니다.
var sum = function fn(){
var total = 0,
l = 인수.length;
for(; l; l--)
{
total = 인수[l-1]
console.info(typeof fn);
return total;
}
console.info(sum(1,2,3,4));//function, 10
console.info( fn(1 ,2,3,4));//ReferenceError


위는 FireFox에서 명명된 함수 표현식을 실행한 결과입니다. 이 이름은 함수 범위에서 액세스할 수 있지만 전역 범위 액세스 중에 참조 예외가 발생했습니다. 그러나 IE9 이전의 IE 브라우저에서는 명명된 함수 표현식이 함수 선언과 함수 표현식 모두로 구문 분석되어 두 개의 객체가 생성됩니다. 다행히 IE9에서는 이를 수정했습니다.

전역 범위 외에도 함수 범위에는 함수의 매개변수도 선언 승격 경쟁에 참여합니다. 먼저 명확하게 짚고 넘어가야 할 점은 함수가 정의될 ​​때는 함수 범위가 존재하지 않는다는 것입니다. 함수가 실제로 호출될 때만 함수 범위가 존재한다는 것입니다.


// 매개변수와 내부변수, 매개변수는 우선순위
function fn(inner){
console.info(inner);// param
console.info(other);// undefine
var inner = 'inner'; other = '기타';
console.info(inner);// 내부
console.info(other);// other
}
fn('param')
// 매개변수 및 내부 함수, 내부 함수가 우선
function gn(inner){
console.info(inner);// inner() function
console.info(inner()); // 정의되지 않음
function inner(){
return other;
}
var other = 'other'
console.info(inner);// inner() 함수
console.info(inner ());// 기타
}
gn('param')


위 출력을 통해 우선순위를 얻습니다: 내부 함수 선언 > 함수 매개변수 > 내부 변수 선언.

여기서의 프로세스 중 하나는 다음과 같습니다. 먼저 내부 함수 선언을 승격하고 함수 이름의 유형을 함수 유형으로 설정한 다음 함수 매개변수를 구문 분석하고 실제 매개변수 값을 전달합니다. in은 형식 매개변수에 할당되며, 마지막으로 내부 변수 선언 승격은 초기화 없이 선언만 승격합니다. 중복된 이름이 있는 경우 우선순위가 같은 이름은 이전 이름을 덮어쓰고 우선순위가 다른 이름은 덮어쓰지 않습니다. 우선순위가 높은 항목은 구문 분석되었으며, 우선순위가 낮은 항목은 더 이상 구문 분석되지 않습니다.
설명하자면, 이는 출력 결과를 기반으로 한 추론일 뿐이며, 배경 구현의 경우 단계가 완전히 반대이고 각 단계가 이전 단계의 결과를 포함하거나 심지어는 다음 단계에서 시작될 수도 있습니다. 그런 다음 우선순위를 정하여 필요한지 여부를 결정합니다. 물론 효율성 측면에서 보면 커버리지가 더 좋다고 판단한 프로세스입니다. 또한 전역 범위는 실제로 함수 매개변수가 없는 함수 범위의 단순화된 버전입니다.

여기서는 포괄적인 예를 제시하지는 않겠습니다. 이전 기본 문법 기사와 함께 이 기사를 읽으면 더 나은 결과를 얻을 수 있습니다. 우선순위와 적용 범위에 관해서도 아래에서 논의할 질문으로 이어집니다.

4. 함수 오버로딩

함수는 객체이고, 함수 이름은 함수 객체를 가리키는 참조형 변수이므로 우리가 할 수 없습니다. 일반적인 객체지향 언어와 동일합니다. 오버로딩 구현:
코드 복사 코드는 다음과 같습니다.

function fn(a){
return a;
}
function fn(a,b){
return a b; info(fn(1)); // NaN
console.info(fn(1,2));// 3


왜 8행이 NaN을 출력하는지 궁금하지 마세요. 함수 이름은 단지 변수일 뿐이며 두 함수 선언은 순서대로 구문 분석됩니다. 이 변수가 최종적으로 가리키는 함수는 두 번째 함수이며, 8행에서는 함수 내에서 1개의 매개변수만 전달합니다. , 1에 더해지면 결과는 NaN이 됩니다. 함수 표현식으로 대체하면 이해하기 쉬울 수 있습니다. 당연히 나중에 할당하면 이전 할당을 덮어쓰게 됩니다.


코드 복사 코드는 다음과 같습니다. var fn = function (a){ return a }
fn = function (a,b){ return a b; }


그렇다면 ECMAScript에서 오버로딩을 어떻게 구현할까요? 간단한 데이터 유형 래퍼 객체(Boolean, Number, String)를 생성자로 사용하여 객체를 생성하고 변환 함수로 사용하여 데이터 유형을 변환할 수 있다는 점을 기억하세요. 사실, 우리는 이전 기사에서 이 오버로딩에 대해 논의했습니다:
(1) 이 방법의 일반적인 형식은 다음과 같습니다:



코드 복사 코드는 다음과 같습니다. function fn(){
if(this instanceof fn)
{
/ / 함수 1
}else
{
// 함수 2
}
}


이 방법은 가능하지만 효과는 분명히 제한적입니다. 오버로드는 두 번만 가능하며 생성자만 오버로드할 수 있습니다. 물론, apply()나 call() 또는 심지어 ES5의 새로운 바인딩()을 결합하여 함수 내에서 this 값을 동적으로 바인딩하여 오버로드를 확장할 수 있지만 이는 이미 함수의 내부 속성을 기반으로 한 오버로드를 의미합니다.
(2) 오버로드



코드 복사 코드는 다음과 같습니다. function fn (){
var length =args.length;
if(0 == length)//리터럴을 왼쪽에 배치하는 것은 Java에서 가져온 습관입니다. 왜냐하면 비교 연산자가 If 할당으로 작성되기 때문입니다. 연산자(0=길이)가 없으면 컴파일러에서 오류 메시지를 표시합니다. 이 방법이 익숙하지 않으시다면 양해 부탁드립니다.
  {
return 0;
}else if(1 == length)
{
return 인수[0]
} else{
return ( 인수[0]) ( 인수[1]);
}
}

console.info(fn());//0
콘솔. info(fn(1));//1
console.info(fn(true));//1
console.info(fn(1,2));//3
콘솔. info(fn('1','2'));//3


여기서는 함수의 내부 속성 인수를 사용하여 오버로딩을 구현합니다. 물론 내부적으로 오버로드하는 방법은 여러 가지가 있으며, typeof, instanceof 등의 연산자를 결합하여 원하는 기능을 구현할 수도 있습니다. 내부 속성 인수는 정확히 무엇입니까? 이것이 제가 아래에서 이야기할 내용입니다.

5. 함수 내부 속성 인수

쉽게 말하면 함수 내부 속성은 함수 본문 내에서만 접근할 수 있는 속성입니다. 함수가 호출될 때 액세스됩니다. 따라서 함수가 호출될 때만 함수의 내부 속성이 구문 분석됩니다. 각 호출에는 해당 구문 분석이 있으므로 동적 특성이 있습니다. 이러한 속성에는 this 및 인수가 포함됩니다. 먼저 인수를 살펴보고 다음 기사에서 이에 대해 이야기하겠습니다.

(1) 함수 정의에 있는 매개변수 목록을 형식 매개변수라고 하며, 함수 호출 시 실제로 전달되는 매개변수를 실제 매개변수라고 합니다. 일반적으로 C 계열 언어에서는 함수를 호출할 때 실제 매개변수가 형식 매개변수와 일치해야 함을 요구하지만, ECMAScript에서는 정의할 때 둘 사이에 제한이 없으며 이를 전달할 때 전달하면 됩니다. 실제 매개변수 2개를 입력하세요. 실제 매개변수 3개를 전달할 수도 있고, 실제 매개변수 1개만 전달할 수도 있고, 매개변수 없이 전달할 수도 있습니다. 이 기능은 오버로딩을 구현하기 위해 함수의 내부 속성을 사용하는 기초입니다.

(2) 형식 매개변수는 동일한 이름을 가질 수도 있지만 실제로 전달되면 나중에 값이 형식 매개변수의 값으로 사용됩니다(이 경우 인수를 사용하여 이전 실제 매개변수):
코드 복사 코드는 다음과 같습니다.

function gn(a ,a){
console.info(a);
console.info(arguments[0])
console.info(arguments[1]); ,2);//2, 1,2
gn(1);//undefine, 1, undefine


이는 실제로 이 기사 앞부분의 명령문 승격에 대한 결론으로 ​​설명할 수 있습니다. : 동일한 우선순위를 가진 나중 항목이 이전 항목을 덮어쓰고, 함수 매개변수를 구문 분석할 때 값도 동시에 구문 분석됩니다. 물론 이런 방식은 보안에 매우 문제가 되기 때문에 ES5의 strict 모드에서는 이름이 중복되는 형식 매개변수를 금지한다.

(3) 실제 매개변수의 값은 형식 매개변수로 받아들여지는데, 실제 매개변수와 형식 매개변수가 일치하지 않는다면 어떻게 될까요? 정답은 인수를 사용하여 저장하는 것입니다. 실제로 실제 매개변수와 형식 매개변수가 일치하더라도 인수 개체는 여전히 존재하며 실제 매개변수를 수락한 형식 매개변수와 동기화됩니다. 이해를 돕기 위해 이 문장을 다듬어 보겠습니다.

•arguments는 배열과 유사한 객체이며 인수 요소는 인수[0], 인수[1] 등 배열 요소와 마찬가지로 대괄호와 인덱스를 통해 액세스할 수 있습니다.
•arguments는 Object에서 상속된 속성 및 메서드(일부 메서드는 재정의됨) 외에도 길이, 호출 수신자 및 호출자와 같은 자체 속성도 포함합니다. 실제 매개변수의 수(정식 매개변수의 개수? 즉 함수 속성 길이), 호출 수신자는 현재 함수 객체를 나타내며, 호출자는 함수 속성 호출자와 구별하기 위해 정의될 뿐이며 그 값은 정의되지 않습니다.
•arguments는 배열과 유사한 객체이지만 실제 배열 객체는 아닙니다. 인수에 대해 배열 객체 메서드를 직접 호출할 수는 없습니다. 이를 호출하려면 먼저 Array.prototype.slice.call을 사용하면 됩니다. (인수)를 사용하여 배열로 변환합니다.
•인수는 함수가 호출될 때 전달된 실제 매개변수를 저장합니다. 0번째 요소는 첫 번째 실제 매개변수를 저장하고, 첫 번째 요소는 두 번째 실제 매개변수를 저장합니다.
•arguments는 실제 매개변수 값을 저장하고, 형식 매개변수는 둘 사이에 동기화 관계가 있으므로 다른 하나도 이에 따라 수정됩니다.
•인수와 형식 매개변수 간의 동기화는 형식 매개변수가 실제로 실제 매개변수를 수신하는 경우에만 존재합니다. 실제 매개변수를 수신하지 않는 형식 매개변수의 경우 이러한 동기화 관계가 없습니다.
Arguments 객체는 매우 강력하지만 성능면에서 어느 정도 손실이 있기 때문에 필요하지 않으면 형식 매개변수를 우선적으로 사용하는 것이 좋습니다.


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

fn(0,-1);
function fn(para1,para2,para3,para4){
console.info(fn.length);//4, 형식 매개변수 수
console.info(arguments.length);//2, 실제 매개변수 수
console.info(arguments.callee === fn);//true, 호출 수신자 객체가 fn 자체를 가리킴
console.info(arguments.caller);//정의되지 않음
console.info(arguments.constructor);//Array()가 아닌 Object()
try{
arguments.sort();/ /Array-like 결국 배열이 아니고 배열 메서드를 직접 호출할 수 없습니다.
}catch(e){
console.info(e);//TypeError
}
var arr = Array.prototype.slice .call(arguments);//먼저 배열로 변환
console.info(arr.sort());//[-1,0], 이미 정렬됨

console.info( para1);//0
arguments[0] = 1;
console.info(para1);//1, 인수[0]을 수정하면 형식도 동시에 수정됩니다. para1

console.info(arguments[1]);//-1
para2 = 2
console.info(arguments[1]);//2, 형식 매개변수 수정 para2는 동시에 인수[1]

console.info(para3);//정의되지 않음, 전달된 실제 매개변수가 없는 형식 매개변수는 정의되지 않음
arguments[2] =
console입니다. info(arguments[2]);// 3
console.info(para3);//정의되지 않음, 실제 매개변수를 허용하지 않는 형식 매개변수는 동기화 관계가 없습니다

console.info(arguments[3 ]);//정의되지 않음, 실제 매개변수가 전달되지 않음, 값이 정의되지 않음
para4 = 4
console.info(para4);//4
console.info(arguments[3]) ;//정의되지 않은 실제 매개변수가 전달되어 동기화되지 않습니다
}

테스트 후 인수와 형식 매개변수 간의 동기화는 양방향이지만 " JavaScript 고급 프로그래밍(3판)"은 단방향이라고 말합니다. 형식 매개변수를 수정해도 인수는 변경되지 않습니다. 이는 원본 책의 또 다른 버그일 수도 있고 FireFox가 사양을 확장했을 수도 있습니다. 그러나 이는 고전적이라 할지라도 여전히 버그의 가능성이 있으며 모든 것이 실제 작동되어야 한다는 것을 알려줍니다.

//팩토리얼 찾기
함수 팩토리얼 (숫자) {
if(숫자 {
return 1;
}else{
return num * 계승(숫자 - 1)
>}
var fn =factorial;
factorial = null;
try{
fn(2);//factorial은 함수 내에서 재귀적으로 호출되고 계승에는 null 값이 할당되었기 때문입니다. , 예외 발생
}catch(e){
console.info(e);//TypeError
}

//피보나치 수열
function fibonacci(num){
if(1 == 숫자 || 2 == 숫자){
return 1;
}else{
return 인수.callee(숫자 - 1) Argument.callee(숫자 - 2);
}
}
var gn = fibonacci;
fibonacci = null;
console.info(gn(9));//34는args.callee를 사용하여 함수 객체를 구현하고 함수명 Decoupling 하면 정상적으로 실행 가능


재귀 알고리즘은 매우 간단하지만 실행 중인 스택을 유지해야 하기 때문에 효율성이 그다지 좋지 않습니다. 재귀 최적화와 관련하여 매우 유용한 알고리즘도 많이 있으므로 여기서는 깊이 다루지 않겠습니다.
코드 복사


코드는 다음과 같습니다.

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿