함수는 JavaScript에서 가장 중요한 코드 구성 요소 중 하나입니다.

함수는 일련의 명령으로 구성되며 일반적으로 하나의 특정 작업(예: 숫자 합산, 근 계산 등)을 수행합니다.

함수에 배치된 코드는 해당 함수를 명시적으로 호출한 후에만 실행됩니다.

함수 선언

1.통사론:

//함수 선언 function FunctionName(var1, var2)( 함수 코드 ) //함수 호출 FunctionName(var1,var2);

2. 통사론:

//함수 선언 var functionname=function(var1, var2)(함수 코드) //함수 호출 functionname(var1,var2);

함수 이름함수의 이름을 지정합니다. 페이지의 각 기능에는 고유한 이름이 있어야 합니다. 함수 이름은 라틴 문자로 지정해야 하며 숫자로 시작하면 안 됩니다.

1당그리고 2당함수 내에서 전달할 수 있는 변수 또는 값입니다. 각 함수에 무제한의 변수를 전달할 수 있습니다.

메모:함수에 변수가 전달되지 않더라도 함수 이름 뒤에 괄호 "()"를 삽입하는 것을 잊지 마십시오.

메모: JavaScript의 함수 이름은 대소문자를 구분합니다.

자바스크립트 함수 예시

아래 예제의 messageWrite() 함수는 버튼을 클릭한 후에만 실행됩니다.

메모:이 예제에서는 onclick 이벤트를 사용합니다. 자바스크립트 이벤트이 자습서의 뒷부분에서 자세히 설명합니다.

함수에 변수 전달

함수에 무제한의 변수를 전달할 수 있습니다.

메모:함수 내부의 변수에 대한 모든 조작은 실제로 변수 자체가 아니라 해당 복사본에서 수행되므로 변수 자체의 내용은 함수 실행의 결과로 변경되지 않습니다.

/* 전달된 변수에 10을 더하고 페이지에 결과를 출력하는 함수를 정의합니다. */ function plus(a)( a=a+10; document.write("Function output: " + a+"
"); ) var a=25; document.write("함수 호출 전 변수 값: "+a+"
"); // 변수를 전달하는 함수 호출 a plus(a); document.write("함수 호출 후 변수의 값: "+a+"
");

퀵뷰

함수의 복사본이 아닌 함수에서 전역 변수에 액세스하려면 다음을 사용하십시오. window.variable_name.

함수 plus(a)( window.a=a+10; ) var a=25; document.write("함수 호출 전 변수 값: "+a+"
"); plus(a); document.write("함수 호출 후 변수 값: "+a+"
");

퀵뷰

반환 명령

명령으로 반품함수에서 값을 반환할 수 있습니다.

퀵뷰

내장 함수

JavaScript의 사용자 정의 함수 외에도 내장 함수.

예를 들어 내장 함수 isFinite전달된 값이 유효한 숫자인지 확인할 수 있습니다.

Document.write(isFinite(40)+"
"); document.write(isFinite(-590)+"
"); document.write(isFinite(90.33)+"
"); document.write(isFinite(NaN)+"
"); document.write(isFinite("이것은 문자열입니다")+"
");

퀵뷰

메모: 전체 목록에서 찾을 수 있는 내장 JavaScript 함수

지역 및 전역 변수

함수 내부에서 생성된 변수를 호출 지역 변수. 이러한 변수는 정의된 함수 내에서만 액세스할 수 있습니다.

함수 코드를 실행한 후 이러한 변수는 소멸됩니다. 이것은 같은 이름을 가진 변수가 다른 함수에서 정의될 수 있음을 의미합니다.

함수 코드 외부에서 생성된 변수를 호출합니다. 전역 변수이러한 변수는 코드의 어디에서나 액세스할 수 있습니다.

함수 내에서 var 없이 변수를 선언하면 전역 변수도 됩니다.

전역 변수는 페이지가 닫힐 때만 소멸됩니다.

퀵뷰

메모:표시될 때 func1은 var2의 로컬 "버전"에서 작동하기 때문에 var2는 null이 됩니다.

익명 함수 사용

선언할 때 이름을 포함하지 않는 함수가 호출됩니다. 익명의.

익명 함수는 기본적으로 코드에서 일반 함수로의 후속 호출이 아니라 다른 함수에 매개변수로 전달하기 위해 선언됩니다.

함수 arrMap(arr,func)( var res=new 배열; for (var i=0;i ");

퀵뷰

너 스스로해라

연습 1. 아래 코드의 오류를 수정하십시오.

연습 1

코드의 오류를 수정합니다.

작업 2.

  1. 다른 매개변수를 전달할 때 동작을 검사하여 함수 1-3의 코드를 재현합니다.
  2. 기능과 상호 작용하여 키워드를 결정 4.

작업 2

//첫 번째 비밀 함수 호출 document.write(secfunc1(4,12) + "
"); // 두 번째 비밀 함수 호출 document.write(secfunc2(100,10) + "
"); //세 번째 비밀 함수 호출 secfunc3(23,10); document.write("
"); // 네 번째 비밀 함수 호출 secfunc4("p");

Disqus 댓글 시스템을 사용하려면 JavaScript를 활성화하십시오.

사람들은 컴퓨터 과학이 천재를 위한 예술이라고 생각합니다. 실제로는 그 반대가 사실입니다. 많은 사람들이 마치 작은 자갈로 된 벽을 만드는 것처럼 서로의 위에 서서 일을 하고 있습니다.

도널드 크누스

이미 alert 와 같은 함수 호출을 보았습니다. 함수는 JavaScript 프로그래밍의 빵과 버터입니다. 프로그램의 일부를 래핑하고 변수로 호출하는 아이디어는 매우 인기가 있습니다. 큰 프로그램을 구조화하고, 반복을 줄이고, 서브루틴에 이름을 지정하고, 서브루틴을 서로 분리하기 위한 도구입니다.

함수의 가장 분명한 용도는 새 사전을 만드는 것입니다. 평범한 인간의 산문에 대한 단어를 생각해내는 것은 나쁜 형식입니다. 프로그래밍 언어에서는 이것이 필요합니다.

평균적인 성인 러시아어 사용자는 약 10,000단어를 알고 있습니다. 드문 프로그래밍 언어에는 10,000개의 내장 명령이 포함되어 있습니다. 그리고 프로그래밍 언어의 어휘는 더 명확하게 정의되어 있으므로 인간보다 융통성이 떨어집니다. 따라서 불필요한 반복을 피하기 위해 일반적으로 우리 자신의 단어를 추가해야 합니다.

기능 정의

함수 정의는 변수가 받는 값이 함수인 일반 변수 정의입니다. 예를 들어, 다음 코드는 주어진 숫자의 제곱을 계산하는 함수를 참조하는 변수 square를 정의합니다.

var 정사각형 = function(x) ( return x * x; ); console.log(사각형(12)); // → 144

함수는 function 키워드로 시작하는 표현식으로 생성됩니다. 함수에는 매개변수 세트(이 경우 x만)와 함수가 호출될 때 실행될 명령이 포함된 본문이 있습니다. 함수의 본문은 단일 문으로 구성되어 있더라도 항상 중괄호로 묶입니다.

함수에는 여러 매개변수가 있거나 전혀 없을 수 있습니다. 다음 예에서 makeNoise에는 매개변수 목록이 없지만 power에는 두 개의 매개변수 목록이 있습니다.

Var makeNoise = function() ( console.log("젠장!"); ); 소음을(); // → 젠장! var power = function(base, exponent) ( var result = 1; for (var count = 0; count)< exponent; count++) result *= base; return result; }; console.log(power(2, 10)); // → 1024

거듭제곱 및 제곱과 같은 일부 함수는 값을 반환하지만 makeNoise와 같이 부작용만 있는 다른 함수는 반환하지 않습니다. return 문은 함수가 반환하는 값을 정의합니다. 프로그램 처리가 이 명령어에 도달하면 즉시 함수를 종료하고 이 값을 함수가 호출된 코드의 위치로 반환합니다. 표현식 없이 반환하면 undefined 가 반환됩니다.

매개변수 및 범위

함수 매개 변수는 변수와 같지만 초기 값은 코드가 아니라 함수가 호출될 때 설정됩니다.

함수의 중요한 속성은 함수 내에서 생성된 변수(매개변수 포함)가 해당 함수 내에서 지역적이라는 것입니다. 즉, power 예제에서 변수 result는 함수가 호출될 때마다 생성되며 이러한 별도의 구현은 어떤 식으로든 서로 관련이 없습니다.

이 변수의 지역성은 함수 내부에서 생성된 매개변수와 변수에만 적용됩니다. 함수 외부에 설정된 변수는 프로그램 전체에서 볼 수 있으므로 전역 변수라고 합니다. 같은 이름의 지역 변수를 선언하지 않은 경우 함수 내에서 이러한 변수에 액세스할 수도 있습니다.

다음 코드는 이를 보여줍니다. x에 값을 할당하는 두 개의 함수를 정의하고 호출합니다. 첫 번째는 로컬로 선언하여 로컬 변수만 변경합니다. 두 번째 것은 선언하지 않으므로 함수 내에서 x로 작업하는 것은 예제의 시작 부분에서 설정한 전역 변수 x를 참조합니다.

var x = "외부"; var f1 = function() ( var x = "f1 내부"; ); f1(); 콘솔 로그(x); // → 외부 var f2 = function() ( x = "inside f2"; ); f2(); 콘솔 로그(x); // → f2 내부

이 동작은 함수 간의 우발적인 상호 작용을 방지하는 데 도움이 됩니다. 모든 변수가 프로그램의 어느 곳에서나 사용된다면, 하나의 변수가 다른 목적으로 사용되지 않도록 하는 것은 매우 어려울 것입니다. 그리고 변수를 재사용한다면 제3자 코드가 변수 값을 엉망으로 만드는 이상한 효과를 보게 될 것입니다. 함수 지역 변수를 함수 내에서만 존재하도록 처리함으로써 언어는 함수를 별도의 작은 우주인 것처럼 사용할 수 있으므로 전체 코드에 대해 걱정할 필요가 없습니다.

중첩 범위

JavaScript는 전역 변수와 지역 변수를 구별할 뿐만 아니라 함수는 함수 내에서 정의될 수 있으며 결과적으로 여러 수준의 지역성을 갖게 됩니다.

예를 들어, 다음의 다소 의미 없는 함수에는 내부에 두 가지가 더 포함되어 있습니다.

var 풍경 = function() ( var 결과 = ""; var 플랫 = function(크기) ( for (var count = 0; count)< size; count++) result += "_"; }; var mountain = function(size) { result += "/"; for (var count = 0; count < size; count++) result += """; result += "\\"; }; flat(3); mountain(4); flat(6); mountain(1); flat(1); return result; }; console.log(landscape()); // → ___/""""\______/"\_

flat 및 mountain 함수는 정의된 함수 내부에 있기 때문에 결과 변수를 봅니다. 그러나 그들은 한 함수의 변수가 다른 함수의 범위 밖에 있기 때문에 서로의 카운트 변수를 볼 수 없습니다. 그리고 랜드스케이프 함수 외부의 환경은 이 함수 내부에 정의된 어떤 변수도 볼 수 없습니다.

즉, 각 로컬 범위에서 이를 포함하는 모든 범위를 볼 수 있습니다. 함수 내에서 사용할 수 있는 변수 집합은 프로그램에서 이 함수가 선언된 위치에 따라 결정됩니다. 주 프로그램의 최상위 수준에서 정의된 변수를 포함하여 함수 정의를 둘러싼 블록의 모든 변수를 볼 수 있습니다. 범위에 대한 이러한 접근 방식을 어휘라고 합니다.

다른 프로그래밍 언어를 공부한 사람들은 중괄호로 묶인 모든 블록이 자체 로컬 환경을 생성한다고 생각할 수 있습니다. 그러나 JavaScript에서는 함수만 범위를 만듭니다. 독립형 블록을 사용할 수 있습니다.

var 뭔가 = 1; ( var something = 2; // 변수로 무엇인가... ) // 블록 종료...

그러나 블록 내부의 무언가는 외부와 동일한 변수입니다. 이러한 블록이 허용되지만 if 문 및 루프에만 사용하는 것이 좋습니다.

이것이 당신에게 이상하게 여겨진다면 당신에게만 그런 것이 아닌 것 같습니다. JavaScript 1.7은 var처럼 작동하지만 함수뿐만 아니라 주어진 블록에 대해 로컬인 변수를 생성하는 let 키워드를 도입했습니다.

가치로서의 기능

함수 이름은 일반적으로 프로그램 조각의 이름으로 사용됩니다. 이러한 변수는 한 번 설정되고 변경되지 않습니다. 따라서 함수와 이름을 혼동하기 쉽습니다.

그러나 이것은 두 가지 다른 것입니다. 함수 호출은 간단한 변수처럼 사용할 수 있습니다. 예를 들어 모든 표현식에서 사용할 수 있습니다. 함수 호출을 새 변수에 저장하고 다른 함수에 매개변수로 전달하는 등의 작업이 가능합니다. 또한 함수 호출을 저장하는 변수는 일반 변수로 유지되며 값을 변경할 수 있습니다.

Var launchMissiles = function(value) ( ​​​missileSystem.launch("제발!"); ); if (safeMode) launchMissiles = function(value) (/* 릴리스 */);

5장에서 우리는 다른 함수에 함수 호출을 전달함으로써 할 수 있는 놀라운 일들에 대해 논의할 것입니다.

함수 선언

"var square = function…"이라는 표현의 짧은 버전이 있습니다. function 키워드는 문의 시작 부분에 사용할 수 있습니다.

함수 square(x) ( x * x를 반환; )

이것은 함수 선언입니다. 명령문은 변수 square를 정의하고 주어진 기능을 할당합니다. 지금까지는 모든 것이 정상입니다. 그러한 정의에는 단 하나의 함정이 있습니다.

Console.log("미래가 말한다:", future()); function future() ( return "우리는 여전히 하늘을 나는 자동차가 없습니다."; )

이 코드는 함수를 사용하는 코드 아래에 함수가 선언되어 있어도 작동합니다. 이는 함수 선언이 프로그램의 일반적인 하향식 실행의 일부가 아니기 때문입니다. 범위의 맨 위로 "이동"하고 해당 범위의 모든 코드에서 호출할 수 있습니다. 위의 모든 함수가 사용되는 위치에 정의해야 하는 것에 대해 걱정할 필요 없이 가장 의미 있는 순서로 코드를 작성할 수 있기 때문에 때때로 편리합니다.

그러나 조건부 블록이나 루프 내부에 함수 선언을 배치하면 어떻게 될까요? 그렇게 할 필요가 없습니다. 역사적으로 JavaScript를 실행하는 플랫폼마다 이러한 경우를 다르게 처리했으며 현재 언어 표준에서는 이를 금지합니다. 프로그램을 일관되게 실행하려면 다른 함수나 주 프로그램 내에서만 함수 선언을 사용하십시오.

Function example() ( function a() () // 규칙 if (something) ( function b() () // Ay-yy-yy! ) )

호출 스택
실행 순서가 함수와 어떻게 작동하는지 자세히 살펴보는 것이 도움이 됩니다. 다음은 몇 가지 함수 호출이 있는 간단한 프로그램입니다.

함수 Greeting(who) ( console.log("안녕하세요, " + who); ) Greeting("Semyon"); console.log("포케다");

이는 다음과 같이 처리됩니다. Greeting을 호출하면 패스가 함수의 시작 부분으로 건너뛰게 됩니다. 제어를 수행하고 제어를 반환하는 내장된 console.log 함수를 호출합니다. 그런 다음 인사의 끝에 도달하고 호출 된 장소로 돌아갑니다. 다음 줄은 console.log를 다시 호출합니다.

도식적으로 이것은 다음과 같이 표시될 수 있습니다.

맨 위로 인사 console.log 맨 위로 인사 console.log 맨 위로

함수는 호출된 위치로 돌아가야 하므로 컴퓨터는 함수가 호출된 컨텍스트를 기억해야 합니다. 한 경우에는 console.log가 다시 Greeting으로 변경되어야 합니다. 다른 프로그램에서는 프로그램의 끝으로 돌아갑니다.

컴퓨터가 컨텍스트를 기억하는 곳을 스택이라고 합니다. 함수가 호출될 때마다 현재 컨텍스트가 스택 맨 위에 푸시됩니다. 함수가 반환되면 스택에서 최상위 컨텍스트를 꺼내 계속 사용합니다.

스택 스토리지에는 메모리 공간이 필요합니다. 스택이 너무 커지면 컴퓨터는 실행을 중지하고 "스택 오버플로" 또는 "너무 많은 재귀"와 같은 문제를 발생시킵니다. 다음 코드는 이를 보여줍니다. 두 기능 사이를 끝없이 점프하게 만드는 매우 복잡한 질문을 컴퓨터에 합니다. 보다 정확하게는 컴퓨터에 무한 스택이 있는 경우 무한 점프가 됩니다. 실제로는 스택이 오버플로됩니다.

Function 치킨() ( return egg(); ) function egg() ( return 치킨(); ) console.log(chicken() + "가 먼저 왔습니다."); // → ??

선택적 인수
다음 코드는 완전히 합법적이며 문제 없이 실행됩니다.

Alert("안녕하세요", "안녕하세요!", "안녕하세요!");

공식적으로 함수는 하나의 인수를 취합니다. 하지만 이런 도전에 그녀는 불평하지 않는다. 나머지 인수를 무시하고 "Hello"를 표시합니다.

JavaScript는 함수에 전달되는 인수의 수에 대해 매우 관대합니다. 너무 많이 통과하면 추가 항목은 무시됩니다. 너무 적음 - 누락된 항목에는 정의되지 않은 값이 할당됩니다.

이 접근 방식의 단점은 함수에 잘못된 수의 인수를 전달할 수 있고 심지어 그럴 가능성이 있으며 아무도 이에 대해 불평하지 않는다는 것입니다.

장점은 선택적 인수를 사용하는 함수를 만들 수 있다는 것입니다. 예를 들어, 다음 버전의 거듭제곱 함수에서는 2개와 1개의 인수로 호출할 수 있습니다. 후자의 경우 지수는 2가 되고 함수는 제곱처럼 작동합니다.

함수 power(base, exponent) ( if (exponent == undefined) exponent = 2; var result = 1; for (var count = 0; count< exponent; count++) result *= base; return result; } console.log(power(4)); // → 16 console.log(power(4, 3)); // → 64

다음 장에서는 함수 본문이 전달된 인수의 정확한 수를 어떻게 알 수 있는지 볼 것입니다. 이것은 유용하기 때문에 여러 인수를 취하는 함수를 만들 수 있습니다. 예를 들어 console.log는 이 속성을 사용하고 전달된 모든 인수를 출력합니다.

Console.log("R", 2, "D", 2); // → R 2 D 2

폐쇄

함수 호출을 변수로 사용하는 기능과 함께 함수가 호출될 때마다 지역 변수가 다시 생성된다는 사실은 우리를 흥미로운 점으로 이끕니다. 함수가 실패하면 지역 변수는 어떻게 됩니까?

다음 예는 이 문제를 보여줍니다. 지역 변수를 생성하는 wrapValue 함수를 선언합니다. 그런 다음 해당 지역 변수를 읽고 값을 반환하는 함수를 반환합니다.

함수 wrapValue(n) ( var localVariable = n; return function() ( return localVariable; ); ) var wrap1 = wrapValue(1); var wrap2 = wrapValue(2); 콘솔 로그(wrap1()); // → 1 console.log(wrap2()); // → 2

이것은 유효하고 정상적으로 작동합니다. 변수에 대한 액세스는 유지됩니다. 또한 동일한 변수의 여러 인스턴스가 동시에 존재할 수 있으므로 각 함수 호출 시 지역 변수가 다시 생성된다는 사실을 더욱 확인합니다.

지역 변수의 일부 인스턴스에 대한 참조로 작업하는 이 기능을 클로저라고 합니다. 지역 변수를 닫는 함수를 닫는 함수라고 합니다. 변수 수명에 대해 걱정할 필요가 없을 뿐만 아니라 기능을 창의적으로 사용할 수 있습니다.

약간의 변경으로 우리는 주어진 숫자를 숫자에 곱하는 함수로 예제를 바꿉니다.

Function multiplier(factor) ( return function(number) ( return number * factor; ); ) var 두 번 = multiplier(2); console.log(두 번(5)); // → 10

wrapValue 예제의 localVariable과 같은 별도의 변수는 더 이상 필요하지 않습니다. 매개변수 자체가 지역 변수이기 때문입니다.

이렇게 생각하기 시작하려면 연습이 필요합니다. 멘탈 모델의 좋은 버전은 함수가 코드를 본체에 고정하고 패키지로 포장한다고 상상하는 것입니다. return function(...)(...)이 표시되면 나중에 사용하기 위해 고정된 코드 조각에 대한 제어판으로 생각하십시오.

이 예에서 승수는 두 개의 변수에 저장한 고정된 코드 조각을 반환합니다. 마지막 줄은 변수에 포함된 함수를 호출하여 저장된 코드(반환 번호 * 인수;)를 활성화합니다. 승수가 호출될 때 정의된 요인 변수에 여전히 액세스할 수 있으며 고정 해제(5) 중에 숫자 매개변수로 전달된 인수에도 액세스할 수 있습니다.

재귀

스택이 오버플로되지 않도록 주의하면 함수가 스스로를 호출할 수 있습니다. 이러한 함수를 재귀라고 합니다. 다음은 지수화의 대체 구현 예입니다.

함수 power(base, exponent) ( if (exponent == 0) return 1; else return base * power(base, exponent - 1); ) console.log(power(2, 3)); // → 8

이것이 수학자들이 지수를 정의하는 방법이며, 아마도 이것은 주기보다 개념을 더 우아하게 설명합니다. 이 함수는 다중 곱셈을 달성하기 위해 다른 인수로 여러 번 자신을 호출합니다.

그러나 이 구현에는 문제가 있습니다. 일반적인 JavaScript 환경에서는 루프가 있는 버전보다 10배 더 느립니다. 루핑은 함수를 호출하는 것보다 저렴합니다.

속도 대 우아함의 딜레마는 매우 흥미롭습니다. 인간의 편의와 기계의 편의 사이에는 일정한 간격이 있습니다. 모든 프로그램은 더 크고 복잡하게 만들어 속도를 높일 수 있습니다. 프로그래머는 올바른 균형을 찾아야 합니다.

첫 번째 지수의 경우 inelegant 루프는 매우 간단하고 간단합니다. 재귀로 대체하는 것은 의미가 없습니다. 그러나 종종 프로그램은 가독성을 높여 효율성을 줄이려는 복잡한 개념으로 작동합니다.

여러 번 반복되었으며 완전히 동의하는 기본 규칙 - 프로그램 속도가 느려질 때까지 성능에 대해 걱정하지 마십시오. 그렇다면 가장 오래 지속되는 부품을 찾아 효율성과 우아함을 교환하십시오.

물론 당장 성능을 완전히 무시해서는 안 됩니다. 많은 경우에 지수와 마찬가지로 우아한 솔루션에서 많은 단순성을 얻지 못합니다. 때때로 숙련된 프로그래머는 단순한 접근 방식이 결코 충분히 빠르지 않다는 것을 즉시 알 수 있습니다.

너무 많은 초보 프로그래머가 작은 일에도 효율성에 집착하기 때문에 이것을 꺼냅니다. 결과는 더 크고 복잡하며 오류가 없는 경우가 많습니다. 이러한 프로그램은 작성하는 데 시간이 더 오래 걸리고 종종 훨씬 더 빠르게 작동하지 않습니다.

그러나 재귀는 항상 루프에 대한 덜 효율적인 대안이 아닙니다. 일부 문제는 재귀로 해결하기가 더 쉽습니다. 대부분의 경우 이것은 각각 분기할 수 있는 여러 트리 분기를 순회하는 것입니다.

여기에 수수께끼가 있습니다. 숫자 1부터 시작하여 무한한 수의 숫자를 얻을 수 있습니다. 그런 다음 5를 더하거나 3을 곱합니다. 숫자가 주어졌을 때 그러한 수열을 찾으려는 함수를 어떻게 작성합니까? 주어진 숫자로 이어지는 덧셈과 곱셈? 예를 들어, 숫자 13은 먼저 1에 3을 곱한 다음 5를 두 번 더하여 얻을 수 있습니다. 그리고 숫자 15는 일반적으로 그렇게 얻기가 불가능합니다.

재귀 솔루션:

function findSolution(target) ( function find(start, history) ( if (start == target) return history; else if (start > target) return null; else return find(start + 5, "(" + history + " +) 5)") || find(start * 3, "(" + history + " * 3)"); ) return find(1, "1"); ) console.log(findSolution(24)); // → (((1 * 3) + 5) * 3)

이 예는 반드시 최단 솔루션을 찾는 것은 아닙니다. 모든 것을 만족합니다. 나는 당신이 프로그램이 어떻게 작동하는지 즉시 이해하기를 기대하지 않습니다. 그러나 재귀적 사고에 대한 이 훌륭한 연습의 밑바닥으로 가자.

내부 함수 찾기는 재귀적입니다. 현재 숫자와 해당 숫자에 도달한 방법에 대한 레코드가 포함된 문자열의 두 가지 인수가 필요합니다. 그리고 일련의 단계를 보여주는 문자열이나 null을 반환합니다.

이를 위해 함수는 세 가지 작업 중 하나를 수행합니다. 주어진 숫자가 목표와 같으면 현재 기록은 그것을 달성하기 위한 방법일 뿐이므로 반환됩니다. 주어진 숫자라면 더 많은 목적, 계속해서 곱하고 더하는 것은 의미가 없습니다. 이렇게 하면 증가하기 때문입니다. 그리고 아직 목표에 도달하지 않았다면 함수는 주어진 숫자에서 시작하여 가능한 두 경로를 모두 시도합니다. 그녀는 각각의 방법으로 한 번, 두 번 자신을 소환합니다. 첫 번째 호출이 null이 아닌 경우 반환합니다. 그렇지 않으면 두 번째 것이 반환됩니다.

함수가 원하는 효과를 얻는 방법을 더 잘 이해하기 위해 숫자 13에 대한 솔루션을 찾기 위해 발생하는 호출을 살펴보겠습니다.

찾기(1, "1") 찾기(6, "(1 + 5)") 찾기(11, "((1 + 5) + 5)") 찾기(16, "(((1 + 5) + 5) ) + 5)") 너무 큰 찾기(33, "(((1 + 5) + 5) * 3)") 너무 큰 찾기(18, "((1 + 5) * 3)") 너무 큰 찾기( 3, "(1 * 3)") find(8, "((1 * 3) + 5)") find(13, "(((1 * 3) + 5) + 5)") 찾았습니다!

들여쓰기는 호출 스택의 깊이를 보여줍니다. 처음 find 함수는 (1 + 5) 및 (1 * 3)으로 시작하는 솔루션을 확인하기 위해 자신을 두 번 호출합니다. 첫 번째 호출은 (1 + 5)로 시작하는 솔루션을 찾고 재귀를 사용하여 원하는 숫자보다 작거나 같은 숫자를 생성하는 모든 솔루션을 확인합니다. 찾지 못하고 null을 반환합니다. 그런 다음 연산자 || 옵션(1 * 3)을 검사하는 함수 호출로 이동합니다. 여기서 우리는 운이 좋은데, 세 번째 재귀 호출에서 13을 얻었기 때문입니다. 이 호출은 문자열을 반환하고 각 || 위의 문자열을 전달하여 결과로 솔루션을 반환합니다.

성장 기능

프로그램에 기능을 도입하는 두 가지 정도 자연스러운 방법이 있습니다.

첫째, 유사한 코드를 여러 번 작성합니다. 이것은 피해야 합니다. 코드가 많을수록 프로그램을 이해하려는 사람들이 더 많은 오류와 읽을 자료를 읽을 수 있습니다. 그래서 우리는 반복되는 기능을 가지고 그것을 일치시킵니다. 좋은 이름그리고 함수에 넣습니다.

두 번째 방법은 별도의 기능에 배치할 가치가 있는 몇 가지 새로운 기능의 필요성을 발견하는 것입니다. 함수의 이름으로 시작한 다음 본문을 작성합니다. 함수 자체가 정의되기 전에 함수를 사용하는 코드를 작성하여 시작할 수도 있습니다.

기능의 이름을 지정하는 것이 얼마나 어려운지는 해당 기능을 얼마나 잘 이해하고 있는지 보여줍니다. 예를 들어 보겠습니다. 농장에 있는 소와 닭의 수, 뒤에 "cow"와 "chickens"라는 단어가 오는 두 개의 숫자를 출력하는 프로그램을 작성해야 합니다. 각각이 정확히 세 위치를 차지하도록 앞에 있는 숫자에 0을 추가해야 합니다.

007 소 011 암탉

분명히 두 개의 인수가 있는 함수가 필요합니다. 코딩을 시작해 봅시다.
// printFarmInventory 함수 printFarmInventory(cows, 닭) ( var cowString = String(cows); while (cowString.length< 3) cowString = "0" + cowString; console.log(cowString + " Коров"); var chickenString = String(chickens); while (chickenString.length < 3) chickenString = "0" + chickenString; console.log(chickenString + " Куриц"); } printFarmInventory(7, 11);

문자열에 .length를 추가하면 길이를 얻습니다. while 루프는 3자의 문자열을 얻을 때까지 숫자에 선행 0을 추가한다는 것이 밝혀졌습니다.

준비가 된! 그러나 우리가 농부에게 코드를 보내려고 하면(물론 상당한 수표와 함께) 그는 농장에 돼지가 있다고 전화를 걸어 우리에게 말하며 돼지 수의 출력을 추가할 수 있습니까? 프로그램에?

물론 가능합니다. 그러나 이 네 줄의 코드를 복사하여 붙여넣기 시작하면 멈추고 생각할 필요가 있음을 깨닫게 됩니다. 더 나은 방법이 있어야 합니다. 우리는 프로그램을 개선하기 위해 노력하고 있습니다:

// outputZeroPaddedWithLabel function printZeroPaddedWithLabel(number, label) ( var numberString = String(number); while (numberString.length< 3) numberString = "0" + numberString; console.log(numberString + " " + label); } // вывестиИнвентаризациюФермы function printFarmInventory(cows, chickens, pigs) { printZeroPaddedWithLabel(cows, "Коров"); printZeroPaddedWithLabel(chickens, "Куриц"); printZeroPaddedWithLabel(pigs, "Свиней"); } printFarmInventory(7, 11, 3);

공장! 그러나 printZeroPaddedWithLabel이라는 이름은 조금 이상합니다. 출력, 제로 패딩 및 레이블의 세 가지를 하나의 기능으로 결합합니다. 전체 반복 조각을 함수로 채우는 대신 한 가지 개념을 강조해 보겠습니다.

// 0 추가 function zeroPad(number, width) ( var string = String(number); while (string.length< width) string = "0" + string; return string; } // вывестиИнвентаризациюФермы function printFarmInventory(cows, chickens, pigs) { console.log(zeroPad(cows, 3) + " Коров"); console.log(zeroPad(chickens, 3) + " Куриц"); console.log(zeroPad(pigs, 3) + " Свиней"); } printFarmInventory(7, 16, 3);

멋지고 설명적인 이름이 zeroPad인 함수를 사용하면 코드를 더 쉽게 이해할 수 있습니다. 그리고 그것은 우리의 경우뿐만 아니라 많은 상황에서 사용될 수 있습니다. 예를 들어 숫자가 있는 서식이 지정된 테이블을 표시합니다.

기능은 얼마나 스마트하고 다양해야 합니까? 우리는 다음과 같이 쓸 수 있습니다. 가장 간단한 기능, 최대 3자리까지 숫자를 0으로 채우고 분수, 음수, 점 정렬, 보수를 지원하는 멋진 범용 숫자 서식 지정 기능 다른 캐릭터, 등.

경험상 필요한 기능만 추가하는 것이 좋습니다. 때때로 모든 작은 필요를 위한 범용 프레임워크를 만들고 싶은 유혹이 있습니다. 그를 저항하십시오. 당신은 작업을 끝내지 않을 것이지만, 아무도 사용하지 않을 많은 코드를 작성하십시오.

기능 및 부작용

함수는 부작용 때문에 호출되는 함수와 어떤 값을 얻기 위해 호출되는 함수로 크게 나눌 수 있습니다. 물론 이러한 속성을 하나의 기능으로 결합하는 것도 가능합니다.

팜 예제의 첫 번째 도우미 함수인 printZeroPaddedWithLabel은 문자열 인쇄의 부작용 때문에 호출됩니다. 두 번째는 반환 값 때문에 zeroPad입니다. 그리고 두 번째 기능이 첫 번째 기능보다 더 자주 유용하다는 것은 우연이 아닙니다. 값을 반환하는 함수는 부작용을 일으키는 함수보다 서로 결합하기 쉽습니다.

순수 함수는 부작용이 없을 뿐만 아니라 나머지 코드의 부작용에 의존하지 않는 특별한 종류의 값 반환 함수입니다. 예를 들어, 실수로 변경될 수 있는 전역 변수에는 작동하지 않습니다. 다른 곳. 순수한 함수는 동일한 인수로 호출될 때 동일한 결과를 반환합니다(다른 작업은 수행하지 않음) - 이는 꽤 좋습니다. 그녀와 함께 일하는 것은 쉽습니다. 이러한 함수의 호출은 코드의 의미를 변경하지 않고 작업 결과로 정신적으로 대체될 수 있습니다. 그러한 함수를 테스트하고 싶을 때 간단히 호출하고 이 컨텍스트에서 작동하는 경우 어떤 환경에서도 작동하는지 확인할 수 있습니다. 그렇게 순수하지 않은 함수는 많은 요인에 따라 다른 결과를 반환할 수 있으며 테스트하고 설명하기 어려운 부작용이 있습니다.

그러나 깨끗하지 않은 함수를 작성하는 것을 부끄러워하거나 그러한 함수에서 코드의 신성한 정리를 시작해서는 안됩니다. 부작용이 종종 도움이 됩니다. 쓸 방법이 없다 깨끗한 버전 console.log 기능이 있으며 이 기능은 매우 유용합니다. 일부 작업은 부작용을 사용하여 표현하기 쉽습니다.

결과

이 장에서는 고유한 함수를 작성하는 방법을 보여주었습니다. function 키워드가 표현식으로 사용되면 함수 호출에 대한 포인터를 반환합니다. 명령문으로 사용될 때 함수 호출을 할당하여 변수를 선언할 수 있습니다.

기능 이해의 핵심은 로컬 범위입니다. 함수 내부에 선언된 매개변수와 변수는 지역적이며 호출될 때마다 다시 생성되며 외부에서 볼 수 없습니다. 다른 함수 내에서 선언된 함수는 해당 범위에 액세스할 수 있습니다.

프로그램이 수행하는 다양한 작업을 기능으로 나누는 것은 매우 유용합니다. 스스로 반복할 필요가 없습니다. 책의 장과 섹션이 일반 텍스트를 구성하는 데 도움이 되는 것과 같은 방식으로 함수는 코드를 의미론적 부분으로 분리하여 코드를 더 읽기 쉽게 만듭니다.

수업 과정

최저한의
이전 장에서 가장 작은 인수를 반환하는 Math.min 함수에 대해 언급했습니다. 이제 우리는 그러한 함수를 직접 작성할 수 있습니다. 두 개의 인수를 취하고 그 중 최소값을 반환하는 min 함수를 작성하십시오.

Console.log(최소(0, 10)); // → 0 console.log(min(0, -10)); // → -10

재귀
%(나머지) 연산자를 사용하여 숫자가 짝수인지(% 2) 확인할 수 있음을 보았습니다. 결정하는 또 다른 방법은 다음과 같습니다.

0은 짝수입니다.
단위가 이상합니다.
모든 숫자 N은 N-2와 동일한 패리티를 갖습니다.

이 규칙에 따라 재귀적 isEven 함수를 작성하십시오. 숫자를 가져와 부울 값을 반환해야 합니다.

50과 75에서 테스트하십시오. -1을 지정하십시오. 그녀는 왜 이런 식으로 행동합니까? 어떻게든 고칠 수 있습니까?

50과 75에서 테스트하십시오. -1에서 어떻게 작동하는지 확인하십시오. 왜요? 할 수 있나요이것을 고칠 방법을 생각해?

Console.log(isEven(50)); // → 참 console.log(isEven(75)); // → 거짓 console.log(isEven(-1)); // → ??

우리는 콩을 계산합니다.

문자열의 문자 번호 N은 .length로 문자열의 길이를 얻는 것과 유사한 방식으로 .charAt(N)("string".charAt(5))를 추가하여 얻을 수 있습니다. 반환 값은 단일 문자열(예: "k")입니다. 문자열의 첫 번째 문자의 위치는 0이며, 이는 마지막 문자의 위치가 string.length - 1임을 의미합니다. 즉, 두 문자 문자열의 길이는 2이고 문자 위치는 0과 1이 됩니다.

문자열을 인수로 사용하고 문자열의 "B" 문자 수를 반환하는 countBs 함수를 작성하십시오.

그런 다음 두 번째 매개변수를 사용한다는 점을 제외하고는 countB와 약간 비슷하게 작동하는 countChar 함수를 작성합니다. (단순히 "B" 문자의 수를 계산하는 대신) 문자열에서 찾을 문자입니다. 이렇게 하려면 countBs 함수를 다시 작성하십시오.

점프 문 및 예외 처리

JavaScript 언어 연산자의 또 다른 범주는 점프 연산자입니다. 이름에서 알 수 있듯이 이러한 명령문은 JavaScript 인터프리터가 프로그램 코드의 다른 위치로 이동하도록 합니다. break 문은 인터프리터가 루프나 다른 문의 끝으로 점프하도록 합니다. continue 문은 인터프리터가 루프 본문의 나머지 부분을 건너뛰고 루프의 시작 부분으로 돌아가서 새 반복을 시작하도록 합니다. 에 자바스크립트명령문에 이름으로 레이블을 지정할 수 있으므로 break 및 continue 명령문이 어느 루프에 또는 어떤 다른 명령문에 속해 있는지 명시적으로 나타낼 수 있습니다.

return 문은 인터프리터가 호출된 함수에서 호출된 지점으로 다시 이동하고 호출 값을 반환하도록 합니다. throw 문은 예외를 throw하고 블록을 정의하는 try/catch/finally 문과 함께 작동하도록 설계되었습니다. 프로그램 코드예외를 처리합니다. 이것은 다소 복잡한 종류의 점프 명령문입니다. 예외가 발생하면 인터프리터는 호출된 함수의 반환 스택에서 동일한 함수 이상에 있을 수 있는 가장 가까운 외부 예외 처리기로 점프합니다.

이러한 점프 연산자 각각은 다음 하위 섹션에서 더 자세히 설명됩니다.

지시 라벨

모든 명령문은 그 앞에 식별자와 콜론을 표시할 수 있습니다.

식별자: 명령

명령에 태그를 지정할 때 프로그램의 어느 곳에서나 참조로 사용할 수 있는 이름을 지정합니다. 모든 명령을 표시할 수 있지만 루프 및 조건문과 같이 본문이 있는 명령만 표시하는 것이 좋습니다.

루프에 이름을 지정하면 break 및 continue 문에서 루프를 종료하거나 루프의 시작 부분으로 점프하여 다음 반복으로 이동할 수 있습니다. break 및 continue 문은 레이블을 포함할 수 있는 JavaScript 언어의 유일한 문입니다. 나중에 더 자세히 설명합니다. 다음은 레이블이 있는 while 문의 예와 해당 레이블을 사용하는 continue 문의 예입니다.

Mainloop: while (token != null) ( // 프로그램 코드 생략... continue mainloop; // 명명된 루프의 다음 반복으로 이동 )

명령문 레이블로 사용되는 식별자는 다음을 제외한 모든 유효한 JavaScript 식별자일 수 있습니다. 예약어. 레이블 이름은 변수 및 함수 이름과 구분되므로 변수 또는 함수 이름과 일치하는 식별자를 레이블로 사용할 수 있습니다.

지침 레이블은 적용되는 지침 내에서만(물론 그 안에 중첩된 지침 내에서) 정의됩니다. 중첩된 명령어는 포함하는 명령어와 동일한 식별자로 레이블을 지정할 수 없지만 두 개의 독립적인 명령어는 동일한 레이블로 레이블을 지정할 수 있습니다. 레이블이 지정된 지침은 다시 태그를 지정할 수 있습니다. 즉, 모든 명령어에는 여러 레이블이 있을 수 있습니다.

break 문

break 문은 가장 안쪽에 있는 루프 또는 switch 문이 즉시 종료되도록 합니다. 우리는 이미 이전에 switch 문 내에서 break 문을 사용하는 예를 보았습니다. 루프에서 어떤 이유로 루프 실행을 종료해야 할 때 루프를 즉시 종료하는 데 일반적으로 사용됩니다.

주기가 매우 클 때 복잡한 조건완료되면 단일 루프 조건으로 이러한 조건을 표현하는 것보다 break 문으로 이러한 조건을 구현하는 것이 더 쉽습니다. 다음 예에서는 특정 값을 가진 배열 요소를 찾으려고 합니다. 루프는 배열의 끝에 도달하거나 원하는 값이 발견되는 즉시 break 문을 사용하여 일반적인 방식으로 종료됩니다.

Var arr = ["a","b","c","d","e"], 결과; (변수 i = 0; 나는

JavaScript에서는 뒤에 레이블 이름을 지정할 수 있습니다. 예어 break(콜론이 없는 식별자):

break label_name;

break 문을 레이블과 함께 사용하면 명명된 문의 끝으로 이동하거나 실행을 종료합니다. 지정된 레이블이 있는 명령어가 없는 경우 이 형식의 break 문을 사용하려고 하면 구문 오류가 생성됩니다. 명명된 문은 루프나 스위치 문일 필요가 없습니다. 레이블이 지정된 break 문은 포함하는 모든 문에서 "이스케이프"할 수 있습니다. 동봉 지침은 다음과 같을 수도 있습니다. 간단한 블록표시할 목적으로만 중괄호로 묶인 지침.

break 키워드와 레이블 이름 사이에 개행 문자를 삽입할 수 없습니다. 이것은 JavaScript 인터프리터가 누락된 세미콜론을 자동으로 삽입하기 때문입니다. break 키워드와 뒤에 오는 레이블 사이에 코드 줄을 끊으면 인터프리터는 레이블이 없는 이 연산자의 간단한 형식을 의미한다고 가정하고 세미콜론을 추가합니다. .

레이블이 붙은 break 문은 가장 가까운 둘러싸는 루프나 switch 문이 아닌 명령문의 실행을 중단하려는 경우에만 필요합니다.

계속 문

continue 문은 break 문과 유사합니다. 그러나 루프를 종료하는 대신 계속 문은 루프의 새 반복을 시작합니다. continue 문의 구문은 break 문의 구문만큼 간단합니다. continue 문은 레이블과 함께 사용할 수도 있습니다.

레이블이 지정되지 않았든 레이블이 지정되든 계속 문은 루프 본문 내에서만 사용할 수 있습니다. 다른 곳에서 사용하면 구문 오류가 발생합니다. 계속 문이 실행되면 루프의 현재 반복이 중단되고 다음 반복이 시작됩니다. 을 위한 다른 유형주기는 다른 것을 의미합니다.

    while 루프에서는 루프의 시작 부분에 지정된 표현식을 다시 확인하고 true이면 루프의 본문을 처음부터 실행합니다.

    do/while 루프는 루프가 반복되기 전에 조건이 다시 확인되는 루프의 끝으로 점프합니다.

    for 루프에서 증분 표현식이 평가되고 테스트 표현식이 다시 평가되어 다음 반복을 수행해야 하는지 여부를 결정합니다.

    for/in 루프에서 루프는 지정된 할당으로 새로 시작됩니다. 이름 변수다음 속성.

while 및 for 루프에서 계속 문의 동작의 차이점에 유의하십시오. while 루프는 해당 조건으로 직접 반환되며, for 루프먼저 증분 식을 평가한 다음 조건으로 돌아갑니다. 다음 예제에서는 레이블이 지정되지 않은 continue 문을 사용하여 짝수에 대한 루프의 현재 반복을 종료하는 방법을 보여줍니다.

변수 합계 = 0; // (var i = 0; i에 대해 0 - 10 사이의 홀수의 합을 계산합니다.

break와 같은 continue 문은 레이블을 포함하는 형식의 중첩 루프에서 사용할 수 있습니다. 이 경우 루프가 다시 시작되었다고 반드시 바로 continue 문을 포함하는 것은 아닙니다. 또한 break와 마찬가지로 continue 키워드와 레이블 이름 사이에 줄 바꿈이 허용되지 않습니다.

반환 문

함수 호출은 표현식이며 모든 표현식과 마찬가지로 값이 있습니다. 함수 내부의 return 문은 함수가 반환하는 값을 결정하는 데 사용됩니다. return 문은 함수 본문에만 넣을 수 있습니다. 다른 곳에서 존재하는 것은 구문 오류입니다. return 문이 실행될 때 함수는 표현식의 값을 호출 프로그램에 반환합니다. 예를 들어:

함수에 return 문이 없으면 호출될 때 인터프리터는 함수의 끝에 도달할 때까지 함수 본문의 명령을 하나씩 실행한 다음 호출한 프로그램에 제어를 반환합니다. 이 경우 호출 식은 undefined를 반환합니다. return 문은 종종 함수의 마지막 문이지만 이것은 완전히 선택 사항입니다. 함수 본문의 다른 문이 뒤에 오는 경우에도 return 문에 도달하는 즉시 함수가 호출 프로그램에 제어를 반환합니다.

return 문은 표현식 없이도 사용할 수 있습니다. 이 경우 단순히 함수를 중단하고 호출자에게 undefined를 반환합니다. 예를 들어:

Function myFun(arr) ( // 배열에 음수가 포함되어 있으면 함수를 중단합니다. for (var i = 0; i

throw 문

예외어떤 종류의 예외 또는 오류가 발생했음을 나타내는 신호입니다. 예외 발생(throw)이러한 오류 또는 예외를 알리는 방법입니다. catch(catch)는 예외를 처리하는 것을 의미합니다. 예외로부터 복구하기 위해 필요하거나 적절한 조치를 취하십시오.

JavaScript에서 런타임 오류가 발생하고 프로그램이 throw 문으로 명시적으로 오류를 발생시키면 예외가 throw됩니다. 예외는 나중에 설명하는 try/catch/finally 문을 사용하여 catch됩니다.

throw 문에는 다음 구문이 있습니다.

던지기 표현;

표현식의 결과는 모든 유형의 값이 될 수 있습니다. throw 문에는 오류 코드를 나타내는 숫자 또는 오류 메시지 텍스트가 포함된 문자열이 전달될 수 있습니다. JavaScript 인터프리터는 클래스의 인스턴스를 사용하여 예외를 throw합니다. 오류하위 클래스 중 하나이며 유사한 접근 방식을 사용할 수도 있습니다. Error 개체에는 속성이 있습니다. 이름, 오류 유형을 정의하는 속성 및 속성 메시지생성자 함수에 전달된 문자열을 포함하는 A. 다음은 잘못된 인수로 호출될 때 Error 객체를 발생시키는 함수의 예입니다.

// 숫자의 계승 함수 function factorial(number) ( // 입력 인수가 아닌 경우 유효한 값, // 예외가 발생했습니다! if (숫자 1; i *= 숫자, 숫자--); /* 빈 루프 본문 */ return i; ) 콘솔.log("5! = ", factorial(5)); console.log("-3! = ", 계승(-3));

예외가 발생하면 JavaScript 인터프리터는 정상적인 프로그램 실행을 즉시 중단하고 가장 가까운 예외 처리기로 이동합니다. 예외 처리기는 다음 섹션에서 설명하는 try/catch/finally 구성의 catch 문을 사용합니다.

예외가 발생한 코드 블록에 해당하는 catch 구문이 없으면 인터프리터는 다음을 구문 분석합니다. 실외기프로그램 코드와 예외 처리기가 연결되어 있는지 확인합니다. 이것은 핸들러를 찾을 때까지 계속됩니다.

예외를 처리하기 위한 try/catch/finally 구문이 포함되지 않은 함수에서 예외가 발생하면 예외는 함수를 호출한 코드로 전파됩니다. 이런 식으로 예외는 어휘 구조를 따라 전파됩니다. 자바스크립트 메소드호출 스택을 올립니다. 예외 처리기가 발견되지 않으면 예외는 오류로 처리되어 사용자에게 보고됩니다.

시도/잡기/마침내 구성

try/catch/finally 구성은 JavaScript의 예외 처리 메커니즘을 구현합니다. 문을 시도이 구성에서 단순히 예외가 처리되는 코드 블록을 정의합니다. try 블록 다음에 catch 문 try 블록의 어느 곳에서나 예외가 발생하면 호출될 명령문 블록이 있습니다. catch 문 뒤에 블록이 옵니다. 마지막으로 A는 최종 작업을 수행하는 코드를 포함하고 try 블록에서 어떤 일이 발생하는지에 관계없이 실행이 보장됩니다.

catch 블록과 finally 블록은 모두 선택 사항이지만 그 중 적어도 하나는 try 블록 뒤에 있어야 합니다. try, catch 및 finally 블록 시작 및 끝 중괄호. 이것은 구문의 필수 부분이며 둘 사이에 명령문이 하나만 있어도 생략할 수 없습니다.

다음 스니펫은 try/catch/finally 구성의 구문과 목적을 보여줍니다.

Try ( // 일반적으로 이 코드는 처음부터 끝까지 순조롭게 실행됩니다. // 하지만 어느 시점에서 예외를 throw할 수 있습니다. // throw 문으로 직접 또는 // 간접적으로 예외를 throw하는 메서드를 호출하여 // 예외. ) catch (ex) ( // 이 블록의 명령문은 try 블록에서 예외가 발생하는 경우에만 실행됩니다. // 이러한 명령문은 Error 개체 또는 다른 개체를 참조하는 // 지역 변수 ex를 사용할 수 있습니다. throw 문에 지정된 값. // 이 블록은 예외를 처리하거나 // 무시하고 다른 작업을 수행하거나 // throw 문으로 예외를 다시 throw할 수 있습니다. ) finally ( // 이 블록에는 명령문이 포함되어 있습니다. 여부에 관계없이 항상 실행됩니다. // try 블록에서 발생한 일 try 블록이 종료되면 실행됩니다. // 1) 평소와 같이 블록의 끝에 도달 // 2) break, continue 또는 return으로 인해 명령문 // 3) 예외 처리 위의 catch 블록에서 // ​4) 계속해서 // 상위 수준으로 전파되는 잡히지 않은 예외와 함께)

catch 키워드 뒤에 괄호 안에 식별자가 옵니다. 이 식별자는 함수 매개변수와 유사합니다. 예외가 발생하면 이 매개변수는 예외로 설정됩니다(예: Error 개체). 일반 변수와 달리 catch 문과 관련된 식별자는 catch 블록의 본문에만 존재합니다.

다음은 try/catch 구문의 보다 현실적인 예입니다. 이전 예제에서 정의한 factorial() 메서드를 호출하고, 프롬프트 방법() 및 alert() 클라이언트 측 JavaScript를 사용하여 입력 및 출력 구성:

Try( // 사용자에게 숫자를 요청 var n = Number(prompt("Enter a positive number", "")); // 입력이 유효하다고 가정하고 // 숫자의 계승을 계산합니다. var f = factorial( n); // 결과를 출력합니다. alert(n + "! = " + f); ) catch (ex) ( // 데이터가 올바르지 않으면 제어가 여기로 이동합니다. alert(ex); // 사용자에게 알림 오류 )

사용자가 음수를 입력하면 경고 메시지가 표시됩니다.

이것은 finally 문이 없는 try/catch 구문의 예입니다. finally는 catch만큼 자주 사용되지는 않지만 그럼에도 불구하고 때때로 유용합니다. finally 블록은 try 블록의 코드가 어떻게 종료되었는지에 관계없이 적어도 try 블록의 일부가 실행된 경우 실행이 보장됩니다. 이 기능은 일반적으로 시도 연속에서 코드가 실행된 후 최종 작업을 수행하는 데 사용됩니다.

정상적인 상황에서 제어는 try 블록의 끝에 도달한 다음 필요한 최종 작업을 수행하는 finally 블록으로 이동합니다. return, continue 또는 break 문의 결과로 제어가 try 블록을 종료하면 제어가 다른 곳으로 전송되기 전에 finally 블록이 실행됩니다.

try 블록에서 예외가 발생하고 이를 처리할 적절한 catch 블록이 있는 경우 제어는 먼저 catch 블록으로 전달된 다음 finally 블록으로 전달됩니다. 로컬 catch 블록이 없는 경우 제어는 먼저 finally 블록으로 전달된 다음 예외를 처리할 수 있는 가장 가까운 외부 catch 블록으로 이동합니다.

finally 블록 자체가 return, continue, break 또는 throw 문을 사용하거나 예외를 throw하는 메서드를 호출하여 제어를 전송하는 경우 보류 중인 전송이 취소되고 새 전송이 실행됩니다. 예를 들어, finally 블록에서 예외가 발생하면 해당 예외는 이전에 발생한 예외를 대체합니다.

운영자 반품현재 함수를 종료하고 해당 값을 반환합니다.

이 대화형 예제의 소스 코드는 GitHub 리포지토리에 저장됩니다. 프로젝트에 참여하고 싶다면 대화식 예제 https://github.com/mdn/interactive-examples를 복제하십시오.

통사론

반환 [[표현식]]; expression 값이 반환될 표현식입니다. 지정하지 않으면 대신 undefined가 반환됩니다.

설명

함수에서 return 문이 호출되면 실행이 중지됩니다. 함수가 호출된 곳으로 지정된 값을 반환합니다. 예를 들어, 다음 함수는 인수 x(여기서 x는 숫자)의 제곱 값을 반환합니다.

function square(x) ( return x * x; ) var demo = square(3); // 데모 값은 9가 됩니다.

반환 값이 지정되지 않으면 대신 undefined가 반환됩니다.

다음 표현식은 항상 함수 실행을 종료합니다.

반품; true를 반환합니다. 거짓을 반환합니다. 반환 x; x + y / 3을 반환합니다.

자동 세미콜론

function magic(x) ( return function calc(x) ( return x * 42 ); ) var answer = magic(); 답변(1337); // 56154

명세서

사양 상태 논평
ECMAScript 1판(ECMA-262) 기준 원래 정의
ECMA스크립트 5.1(ECMA-262)
기준
ECMAScript 2015(6판, ECMA-262)
이 사양에서 "반환 문"의 정의.
기준
ECMAScript 최신 초안(ECMA-262)
이 사양에서 "반환 문"의 정의.
초안

브라우저 호환성

이 페이지의 호환성 표는 구조화된 데이터에서 생성됩니다. 데이터에 기여하고 싶다면 https://github.com/mdn/browser-compat-data 리포지토리에서 확인하고 변경 사항에 대한 풀 요청을 보내주십시오.

GitHub에서 호환성 데이터 업데이트

컴퓨터이동하는섬기는 사람
크롬가장자리파이어폭스인터넷 익스플로러오페라원정 여행안드로이드 웹뷰안드로이드용 크롬안드로이드용 파이어폭스안드로이드용 오페라iOS의 사파리삼성인터넷노드.js
반품크롬 전체 지원 1 가장자리 전체 지원 12 파이어폭스 전체 지원 1 전체 지원 3 오페라 전체 지원원정 여행 전체 지원웹뷰 안드로이드 전체 지원 1 크롬 안드로이드 전체 지원 18 파이어폭스 안드로이드 전체 지원 4 오페라안드로이드 전체 지원사파리 iOS 전체 지원삼성 인터넷 안드로이드 전체 지원 1.0 노드 전체 지원