JavaScript에서 함수는 "마법의 언어 구조"가 아니라 특별한 종류의 값입니다.
이전에 사용한 구문을 함수 선언 이라고 합니다.
함수 sayHi() { 경고( "안녕하세요" ); }
함수 표현식(Function Expression) 이라는 함수를 생성하는 또 다른 구문이 있습니다.
이를 통해 표현식 중간에 새로운 함수를 생성할 수 있습니다.
예를 들어:
let sayHi = function() { 경고( "안녕하세요" ); };
여기에서 변수 sayHi
값을 가져오는 것을 볼 수 있습니다. 새로운 함수는 function() { alert("Hello"); }
로 생성됩니다. function() { alert("Hello"); }
.
함수 생성은 할당 표현식( =
오른쪽)의 맥락에서 발생하므로 이것이 함수 표현식 입니다.
function
키워드 뒤에는 이름이 없습니다. 함수 표현식에는 이름 생략이 허용됩니다.
여기서는 이를 즉시 변수에 할당하므로 이 코드 샘플의 의미는 동일합니다. "함수를 만들고 sayHi
변수에 넣습니다."
나중에 접하게 될 고급 상황에서는 함수가 생성되고 즉시 호출되거나 나중에 실행되도록 예약될 수 있으며 어디에도 저장되지 않아 익명으로 유지됩니다.
다시 한번 강조하자면, 함수가 어떻게 생성되든 함수는 값입니다. 위의 두 예제 모두 sayHi
변수에 함수를 저장합니다.
alert
사용하여 해당 값을 인쇄할 수도 있습니다.
함수 sayHi() { 경고( "안녕하세요" ); } 경고(안녕하세요); // 함수 코드를 보여줍니다
마지막 줄에서는 sayHi
뒤에 괄호가 없기 때문에 함수가 실행되지 않습니다. 함수 이름을 언급하면 실행이 발생하는 프로그래밍 언어가 있지만 JavaScript는 그렇지 않습니다.
JavaScript에서 함수는 값이므로 값으로 처리할 수 있습니다. 위의 코드는 소스 코드인 문자열 표현을 보여줍니다.
확실히 함수는 sayHi()
처럼 호출할 수 있다는 점에서 특별한 값입니다.
하지만 여전히 가치가 있습니다. 따라서 우리는 다른 종류의 가치와 마찬가지로 작업할 수 있습니다.
함수를 다른 변수에 복사할 수 있습니다:
function sayHi() { // (1) 생성 경고( "안녕하세요" ); } func = sayHi; // (2) 복사 기능(); // 안녕하세요 // (3) 복사본을 실행합니다(작동합니다)! 안녕하세요(); // 안녕하세요 // 이것도 여전히 작동합니다(왜 안될까요?)
위에서 자세한 내용은 다음과 같습니다.
함수 선언 (1)
함수를 생성하고 이를 sayHi
라는 변수에 넣습니다.
라인 (2)
는 이를 func
변수에 복사합니다. 다시 한 번 주의하세요. sayHi
뒤에는 괄호가 없습니다. 만약 그렇다면, func = sayHi()
는 sayHi()
호출의 결과를 func
에 쓰는 것이지, 함수 sayHi
자체에 쓰지는 않을 것입니다.
이제 함수를 sayHi()
및 func()
로 호출할 수 있습니다.
함수 표현식을 사용하여 첫 번째 줄에서 sayHi
선언할 수도 있습니다.
let sayHi = function() { // (1) 생성 경고( "안녕하세요" ); }; func = sayHi; // ...
모든 것이 동일하게 작동합니다.
끝에 세미콜론이 있는 이유는 무엇입니까?
함수 표현식에 왜 세미콜론이 있는지 궁금할 것입니다 ;
끝에 있지만 함수 선언은 다음을 수행하지 않습니다.
함수 sayHi() { // ... } let sayHi = function() { // ... };
대답은 간단합니다. 여기서 함수 표현식은 대입문 내에서 function(…) {…}
으로 생성됩니다. let sayHi = …;
. 세미콜론 ;
명령문 끝에 표시하는 것이 좋습니다. 함수 구문의 일부가 아닙니다.
세미콜론은 let sayHi = 5;
와 같이 더 간단한 할당을 위해 사용됩니다. , 기능 할당을 위한 것도 있습니다.
함수를 값으로 전달하고 함수 표현식을 사용하는 예를 더 살펴보겠습니다.
세 가지 매개변수를 사용하여 ask(question, yes, no)
함수를 작성하겠습니다.
question
질문의 텍스트
yes
대답이 "예"인 경우 실행되는 함수
no
대답이 "No"인 경우 실행되는 함수
함수는 question
을 하고 사용자의 대답에 따라 yes()
또는 no()
를 호출해야 합니다.
함수 질문(질문, 예, 아니오) { if (확인(질문)) yes() 그렇지 않으면 아니오(); } 함수 showOk() { Alert( "동의하셨습니다." ); } 함수 showCancel() { Alert( "실행을 취소했습니다." ); } // 사용법: showOk, showCancel 함수는 질문에 대한 인수로 전달됩니다. Ask("동의하십니까?", showOk, showCancel);
실제로 이러한 기능은 매우 유용합니다. 실제 ask
과 위 예의 주요 차이점은 실제 기능이 간단한 confirm
보다 사용자와 상호 작용하는 데 더 복잡한 방법을 사용한다는 것입니다. 브라우저에서 이러한 기능은 일반적으로 보기 좋은 질문 창을 그립니다. 그러나 그것은 또 다른 이야기입니다.
ask
의 showOk
및 showCancel
인수는 콜백 함수 또는 그냥 콜백 이라고 합니다.
아이디어는 함수를 전달하고 필요할 경우 나중에 "콜백"될 것으로 예상한다는 것입니다. 우리의 경우 showOk
"예" 답변에 대한 콜백이 되고 "아니오" 답변에 대해서는 showCancel
됩니다.
함수 표현식을 사용하여 동등하고 더 짧은 함수를 작성할 수 있습니다.
함수 질문(질문, 예, 아니오) { if (확인(질문)) yes() 그렇지 않으면 아니오(); } 묻다( "동의하시나요?", function() { Alert("동의하셨습니다."); }, function() { Alert("실행을 취소했습니다."); } );
여기서 함수는 ask(...)
호출 내에서 바로 선언됩니다. 이름이 없으므로 익명 이라고 합니다. 이러한 함수는 (변수에 할당되지 않기 때문에) ask
외부에서는 액세스할 수 없지만 이것이 바로 우리가 여기서 원하는 것입니다.
이러한 코드는 스크립트에 매우 자연스럽게 나타나며 이는 JavaScript의 정신입니다.
함수는 "작업"을 나타내는 값입니다.
문자열이나 숫자와 같은 일반 값은 데이터를 나타냅니다.
기능은 동작 으로 인식될 수 있습니다.
변수 간에 전달하고 원할 때 실행할 수 있습니다.
함수 선언과 표현식의 주요 차이점을 공식화해 보겠습니다.
첫째, 구문: 코드에서 이들을 구별하는 방법입니다.
함수 선언: 기본 코드 흐름에서 별도의 문으로 선언된 함수입니다.
// 함수 선언 함수 합계(a, b) { a + b를 반환합니다. }
함수 표현식: 표현식 내부 또는 다른 구문 구조 내부에서 생성된 함수입니다. 여기서는 "대입식" =
오른쪽에 함수가 생성됩니다.
// 함수 표현 합계 = 함수(a, b) { a + b를 반환합니다. };
더 미묘한 차이점은 JavaScript 엔진에 의해 함수가 생성될 때 입니다.
함수 표현식은 실행이 도달하면 생성되며 그 순간부터만 사용할 수 있습니다.
실행 흐름이 할당의 오른쪽으로 전달되면 let sum = function…
– 이제 함수가 생성되고 이제부터 사용할 수 있습니다(할당, 호출 등).
함수 선언이 다릅니다.
함수 선언은 정의되기 전에 호출될 수 있습니다.
예를 들어 전역 함수 선언은 위치에 관계없이 전체 스크립트에서 볼 수 있습니다.
이는 내부 알고리즘 때문입니다. JavaScript가 스크립트 실행을 준비할 때 먼저 스크립트에서 전역 함수 선언을 찾아 함수를 생성합니다. '초기화 단계'라고 생각하면 됩니다.
그리고 모든 함수 선언이 처리된 후 코드가 실행됩니다. 따라서 이러한 기능에 액세스할 수 있습니다.
예를 들어 다음과 같이 작동합니다.
sayHi("John"); //안녕하세요, 존 함수 sayHi(이름) { 경고( `안녕하세요, ${name}` ); }
함수 선언 sayHi
JavaScript가 스크립트 시작을 준비할 때 생성되며 스크립트 안의 모든 곳에서 표시됩니다.
...함수 표현식이라면 작동하지 않을 것입니다.
sayHi("John"); // 오류! let sayHi = function(name) { // (*) 더 이상 마법이 없습니다. 경고( `안녕하세요, ${name}` ); };
함수 표현식은 실행이 도달하면 생성됩니다. 이는 (*)
줄에서만 발생합니다. 너무 늦었어요.
함수 선언의 또 다른 특별한 기능은 블록 범위입니다.
엄격 모드에서 함수 선언이 코드 블록 내에 있으면 해당 블록 내부 어디에서나 볼 수 있습니다. 하지만 그 밖은 아닙니다.
예를 들어 런타임 중에 얻은 age
변수에 따라 welcome()
함수를 선언해야 한다고 가정해 보겠습니다. 그리고 나중에 좀 더 사용해 볼 계획입니다.
함수 선언을 사용하면 의도한 대로 작동하지 않습니다.
let age = 프롬프트("당신의 나이는 몇 살입니까?", 18); // 조건부로 함수 선언 if (나이 < 18) { 함수 환영() { Alert("안녕하세요!"); } } 또 다른 { 함수 환영() { Alert("안녕하세요!"); } } // ...나중에 사용하세요 환영(); // 오류: 환영이 정의되지 않았습니다.
그 이유는 함수 선언이 해당 함수 선언이 있는 코드 블록 내부에서만 볼 수 있기 때문입니다.
또 다른 예는 다음과 같습니다.
나이 = 16이라고 놔두세요; // 16을 예로 들어보겠습니다. if (나이 < 18) { 환영(); // (실행) // | 함수 환영() { // | Alert("안녕하세요!"); // | 함수 선언이 가능합니다. } // | 선언된 블록의 모든 곳에서 // | 환영(); // / (실행) } 또 다른 { 함수 환영() { Alert("안녕하세요!"); } } // 여기서는 중괄호가 부족합니다. // 그래서 우리는 그 안에 만들어진 함수 선언을 볼 수 없습니다. 환영(); // 오류: 환영이 정의되지 않았습니다.
if
외부에서 welcome
표시하려면 어떻게 해야 합니까?
올바른 접근 방식은 함수 표현식을 사용하고 if
외부에서 선언되고 적절한 가시성을 갖는 변수에 welcome
할당하는 것입니다.
이 코드는 의도한 대로 작동합니다.
let age = 프롬프트("당신의 나이는 몇 살입니까?", 18); 환영하자; if (나이 < 18) { 환영합니다 = function() { Alert("안녕하세요!"); }; } 또 다른 { 환영합니다 = function() { Alert("안녕하세요!"); }; } 환영(); // 이제 알았어
아니면 물음표 연산자를 사용하여 더욱 단순화할 수도 있습니다 ?
:
let age = 프롬프트("당신의 나이는 몇 살입니까?", 18); 환영합니다 = (나이 < 18) ? function() { 경고("안녕하세요!"); } : function() { Alert("안녕하세요!"); }; 환영(); // 이제 알았어
함수 선언과 함수 표현식을 언제 선택해야 합니까?
경험상 함수를 선언해야 할 때 가장 먼저 고려해야 할 사항은 함수 선언 구문입니다. 함수가 선언되기 전에 호출할 수 있기 때문에 코드를 구성하는 방법이 더 자유로워집니다.
let f = function(…) {…};
보다 코드에서 function f(…) {…}
찾는 것이 더 쉽기 때문에 가독성도 더 좋습니다. . 함수 선언이 더 "눈에 띕니다".
...그러나 어떤 이유로 함수 선언이 적합하지 않거나 조건 선언이 필요한 경우(방금 예제를 보았습니다) 함수 표현식을 사용해야 합니다.
함수는 값입니다. 코드의 어느 위치에서나 할당, 복사 또는 선언할 수 있습니다.
함수가 기본 코드 흐름에서 별도의 명령문으로 선언된 경우 이를 "함수 선언"이라고 합니다.
함수가 표현식의 일부로 생성된 경우 이를 "함수 표현식"이라고 합니다.
함수 선언은 코드 블록이 실행되기 전에 처리됩니다. 블록의 모든 곳에서 볼 수 있습니다.
함수 표현식은 실행 흐름이 도달하면 생성됩니다.
함수를 선언해야 하는 대부분의 경우 함수 선언이 선언 자체보다 먼저 표시되므로 함수 선언이 더 좋습니다. 이는 코드 구성에 더 많은 유연성을 제공하고 일반적으로 더 읽기 쉽습니다.
따라서 함수 선언이 작업에 적합하지 않은 경우에만 함수 표현식을 사용해야 합니다. 우리는 이 장에서 이에 대한 몇 가지 예를 보았으며 앞으로 더 많은 예를 보게 될 것입니다.