스크립트의 여러 위치에서 비슷한 작업을 수행해야 하는 경우가 많습니다.
예를 들어, 방문자가 로그인하거나 로그아웃할 때, 그리고 다른 곳에 있을 때 보기 좋은 메시지를 표시해야 합니다.
함수는 프로그램의 주요 "구성 요소"입니다. 이를 통해 코드를 반복 없이 여러 번 호출할 수 있습니다.
우리는 이미 alert(message)
, prompt(message, default)
, confirm(question)
과 같은 내장 함수의 예를 살펴보았습니다. 하지만 우리 자신만의 기능을 만들 수도 있습니다.
함수를 생성하려면 함수 선언을 사용할 수 있습니다.
다음과 같습니다:
함수 쇼메시지() { Alert( '안녕하세요 여러분!' ); }
function
키워드가 먼저 오고, 그 다음에는 함수의 이름 , 괄호 사이의 매개변수 목록(위의 예에서는 쉼표로 구분되어 비어 있음, 나중에 예를 볼 것임), 마지막으로 함수의 코드(역시 이름이 지정됨)가 옵니다. 중괄호 사이에 있는 "함수 본문"입니다.
함수명(매개변수1, 매개변수2, ...매개변수N) { // 몸 }
새로운 함수는 showMessage()
라는 이름으로 호출할 수 있습니다.
예를 들어:
함수 쇼메시지() { Alert( '안녕하세요 여러분!' ); } 쇼메시지(); 쇼메시지();
showMessage()
호출은 함수의 코드를 실행합니다. 여기서 우리는 메시지를 두 번 보게 될 것입니다.
이 예는 함수의 주요 목적 중 하나인 코드 중복을 방지하는 것을 명확하게 보여줍니다.
메시지나 표시 방식을 변경해야 하는 경우 한 곳에서 코드를 수정하면 충분합니다. 즉, 메시지를 출력하는 함수입니다.
함수 내부에 선언된 변수는 해당 함수 내부에서만 볼 수 있습니다.
예를 들어:
함수 쇼메시지() { let message = "안녕하세요. 저는 JavaScript입니다!"; // 지역변수 경고( 메시지 ); } 쇼메시지(); // 안녕하세요, 저는 자바스크립트입니다! 경고( 메시지 ); // <-- 오류! 변수가 함수에 대해 로컬입니다.
함수는 외부 변수에도 액세스할 수 있습니다. 예를 들면 다음과 같습니다.
userName = 'John'으로 설정; 함수 쇼메시지() { 메시지 = '안녕하세요, ' + userName; 경고(메시지); } 쇼메시지(); //안녕하세요, 존
이 함수는 외부 변수에 대한 전체 액세스 권한을 갖습니다. 수정할 수도 있습니다.
예를 들어:
userName = 'John'으로 설정; 함수 쇼메시지() { 사용자 이름 = "밥"; // (1) 외부 변수를 변경했습니다. 메시지 = '안녕하세요, ' + userName; 경고(메시지); } 경고(사용자 이름); // 함수 호출 전 John 쇼메시지(); 경고(사용자 이름); // Bob, 값이 함수에 의해 수정되었습니다.
외부 변수는 로컬 변수가 없는 경우에만 사용됩니다.
동일한 이름의 변수가 함수 내부에 선언되면 외부 변수를 숨깁니다 . 예를 들어 아래 코드에서 함수는 로컬 userName
사용합니다. 외부 항목은 무시됩니다.
userName = 'John'으로 설정; 함수 쇼메시지() { userName = "Bob"을 보자; // 지역변수 선언 메시지 = '안녕하세요, ' + userName; // 밥 경고(메시지); } // 함수는 자체 userName을 생성하고 사용합니다. 쇼메시지(); 경고(사용자 이름); // John, 변경되지 않음, 함수가 외부 변수에 액세스하지 않음
전역 변수
위 코드의 외부 userName
과 같이 함수 외부에서 선언된 변수를 global 이라고 합니다.
전역 변수는 모든 함수에서 볼 수 있습니다(로컬 변수에 의해 숨겨지지 않는 한).
전역 변수의 사용을 최소화하는 것이 좋습니다. 최신 코드에는 전역 변수가 거의 없거나 전혀 없습니다. 대부분의 변수는 해당 함수에 상주합니다. 하지만 때로는 프로젝트 수준 데이터를 저장하는 데 유용할 수 있습니다.
매개변수를 사용하여 임의의 데이터를 함수에 전달할 수 있습니다.
아래 예에서 함수에는 from
및 text
두 개의 매개변수가 있습니다.
function showMessage(from, text) { // 매개변수: from, text 경고(from + ': ' + 텍스트); } showMessage('앤', '안녕하세요!'); // 앤: 안녕하세요! (*) showMessage('앤', "무슨 일이에요?"); // 앤: 무슨 일이죠? (**)
함수가 (*)
및 (**)
줄에서 호출되면 지정된 값이 및 text
from
지역 변수에 복사됩니다. 그런 다음 함수는 이를 사용합니다.
여기에 또 하나의 예가 있습니다. from
변수가 있고 이를 함수에 전달합니다. 참고: 함수는 from
변경되지만 함수는 항상 값의 복사본을 가져오기 때문에 변경 사항이 외부에 표시되지 않습니다.
함수 showMessage(from, text) { from = '*' + from + '*'; // "from"을 더 보기 좋게 만듭니다. 경고( + ': ' + 텍스트 ); } 하자 = "앤"; showMessage(from, "안녕하세요"); // *앤*: 안녕하세요 // "from"의 값은 동일합니다. 함수가 로컬 복사본을 수정했습니다. 경고( 에서 ); // 앤
값이 함수 매개변수로 전달되는 경우 이를 인수 라고도 합니다.
즉, 이 용어를 바로잡으면 다음과 같습니다.
매개변수는 함수 선언에서 괄호 안에 나열된 변수입니다(선언 시간 용어임).
인수는 함수가 호출될 때 함수에 전달되는 값입니다(호출 시간 용어임).
매개변수를 나열하는 함수를 선언한 다음 인수 전달을 호출합니다.
위의 예에서 다음과 같이 말할 수 있습니다. " showMessage
함수는 두 개의 매개변수로 선언된 다음 두 개의 인수 from
및 "Hello"
로 호출됩니다."
함수가 호출되었지만 인수가 제공되지 않은 경우 해당 값은 정의되지 undefined
.
예를 들어 앞서 언급한 함수 showMessage(from, text)
단일 인수를 사용하여 호출할 수 있습니다.
showMessage("앤");
그건 오류가 아닙니다. 이러한 호출은 "*Ann*: undefined"
출력합니다. text
값이 전달되지 않으므로 undefined
됩니다.
=
사용하여 함수 선언의 매개변수에 대해 소위 "기본값"(생략된 경우 사용) 값을 지정할 수 있습니다.
function showMessage(from, text = "주어진 텍스트 없음") { 경고( + ": " + 텍스트 ); } showMessage("앤"); // Ann: 텍스트가 제공되지 않음
이제 text
매개변수가 전달되지 않으면 "no text given"
값을 얻게 됩니다.
매개변수가 존재하는 경우에도 기본값이 적용되지만 다음과 같이 엄밀하게는 undefined
와 동일합니다.
showMessage("앤", 정의되지 않음); // Ann: 텍스트가 제공되지 않음
여기서 "no text given"
은 문자열이지만 매개변수가 누락된 경우에만 평가되고 할당되는 더 복잡한 표현식일 수 있습니다. 따라서 다음과 같은 방법도 가능합니다.
함수 showMessage(from, text = anotherFunction()) { // anotherFunction()은 텍스트가 주어지지 않은 경우에만 실행됩니다. // 결과는 텍스트 값이 됩니다. }
기본 매개변수 평가
JavaScript에서는 해당 매개변수 없이 함수가 호출될 때마다 기본 매개변수가 평가됩니다.
위의 예에서 text
매개변수가 제공되면 anotherFunction()
전혀 호출되지 않습니다.
반면에 text
누락될 때마다 독립적으로 호출됩니다.
이전 JavaScript 코드의 기본 매개변수
몇 년 전, JavaScript는 기본 매개변수 구문을 지원하지 않았습니다. 그래서 사람들은 그것을 지정하기 위해 다른 방법을 사용했습니다.
요즘 우리는 오래된 스크립트에서 그것들을 만날 수 있습니다.
예를 들어, undefined
대한 명시적인 확인은 다음과 같습니다.
함수 showMessage(from, text) { if (텍스트 === 정의되지 않음) { text = '텍스트가 제공되지 않음'; } 경고( + ": " + 텍스트 ); }
...또는 ||
연산자:
함수 showMessage(from, text) { // 텍스트 값이 거짓인 경우 기본값을 할당합니다. // text == ""는 텍스트가 전혀 없는 것과 같다고 가정합니다. 텍스트 = 텍스트 || '텍스트가 제공되지 않았습니다.'; ... }
때로는 함수 선언 후 나중 단계에서 매개변수에 기본값을 할당하는 것이 합리적일 때도 있습니다.
함수 실행 중에 매개변수가 전달되었는지 undefined
와 비교하여 확인할 수 있습니다.
함수 showMessage(텍스트) { // ... if (text === undefine) { // 매개변수가 누락된 경우 text = '빈 메시지'; } 경고(텍스트); } 쇼메시지(); // 빈 메시지
...또는 ||
를 사용할 수도 있습니다. 연산자:
함수 showMessage(텍스트) { // 텍스트가 정의되지 않았거나 거짓인 경우 '비어 있음'으로 설정합니다. 텍스트 = 텍스트 || '비어 있는'; ... }
최신 JavaScript 엔진은 nullish 병합 연산자 ??
를 지원합니다. , 0
과 같은 대부분의 잘못된 값을 "정상"으로 간주하는 것이 더 좋습니다.
함수 showCount(count) { // count가 정의되지 않았거나 null인 경우 "unknown"을 표시합니다. Alert(개수 ?? "알 수 없음"); } 쇼카운트(0); // 0 showCount(null); // 알려지지 않은 쇼카운트(); // 알려지지 않은
함수는 호출 코드에 결과로 값을 다시 반환할 수 있습니다.
가장 간단한 예는 두 값을 합하는 함수입니다.
함수 합계(a, b) { a + b를 반환합니다. } 결과 = sum(1, 2); 경고(결과); // 3
지시문 return
함수의 어느 위치에나 있을 수 있습니다. 실행이 도달하면 함수가 중지되고 값이 호출 코드(위의 result
에 할당됨)로 반환됩니다.
단일 함수에서 return
이 여러 번 발생할 수 있습니다. 예를 들어:
함수 checkAge(나이) { if (나이 >= 18) { 사실을 반환; } 또 다른 { return verify('부모님께 허락을 받았나요?'); } } let age = 프롬프트('당신은 몇 살입니까?', 18); if ( checkAge(나이) ) { Alert( '접근권한 부여' ); } 또 다른 { 경고( '액세스가 거부되었습니다' ); }
값 없이 return
사용할 수 있습니다. 그러면 함수가 즉시 종료됩니다.
예를 들어:
함수 showMovie(나이) { if ( !checkAge(나이) ) { 반품; } Alert( "영화를 보여드립니다" ); // (*) // ... }
위 코드에서 checkAge(age)
false
반환하면 showMovie
alert
를 진행하지 않습니다.
빈 return
이 있거나 없는 함수는 undefined
반환합니다.
함수가 값을 반환하지 않는 경우 undefined
반환하는 것과 같습니다.
function doNothing() { /* 비어 있음 */ } 경고( doNothing() === 정의되지 않음 ); // 진실
빈 return
return undefined
와 동일합니다:
함수 doNothing() { 반품; } 경고( doNothing() === 정의되지 않음 ); // 진실
return
과 값 사이에 개행 문자를 추가하지 마세요.
return
의 긴 표현식의 경우 다음과 같이 별도의 줄에 배치하고 싶을 수 있습니다.
반품 (일부 + 긴 + 표현식 + 또는 + 무엇이든 * f(a) + f(b))
JavaScript는 return
뒤에 세미콜론을 사용하기 때문에 작동하지 않습니다. 이는 다음과 동일하게 작동합니다.
반품; (일부 + 긴 + 표현식 + 또는 + 무엇이든 * f(a) + f(b))
따라서 사실상 빈 반환이 됩니다.
반환된 표현식을 여러 줄에 걸쳐 표시하려면 return
과 같은 줄에서 시작해야 합니다. 아니면 최소한 다음과 같이 여는 괄호를 넣으세요.
반품 ( 일부 + 긴 + 표현 + 또는 + 무엇이든 * f(a) + f(b) )
그리고 그것은 우리가 기대하는 대로 작동할 것입니다.
기능은 행동입니다. 그래서 그들의 이름은 대개 동사입니다. 코드를 읽는 사람이 함수의 기능을 알 수 있도록 간결하고 최대한 정확해야 하며 기능이 수행하는 작업을 설명해야 합니다.
동작을 모호하게 설명하는 접두사를 사용하여 기능을 시작하는 것이 널리 퍼져 있습니다. 접두사의 의미에 대해 팀 내에서 합의가 이루어져야 합니다.
예를 들어, "show"
로 시작하는 함수는 일반적으로 무언가를 보여줍니다.
다음으로 시작하는 기능…
"get…"
– 값을 반환합니다.
"calc…"
– 무언가를 계산하다,
"create…"
– 무언가를 생성하다,
"check…"
– 무언가를 확인하고 부울 등을 반환합니다.
그러한 이름의 예:
showMessage(..) // 메시지를 표시합니다. getAge(..) // 나이를 반환합니다(어떻게든 얻음) calcSum(..) // 합계를 계산하고 결과를 반환합니다. createForm(..) // 양식을 생성하고 일반적으로 이를 반환합니다. checkPermission(..) // 권한을 확인하고 true/false를 반환합니다.
접두어를 사용하면 함수 이름을 보면 해당 함수가 수행하는 작업 종류와 반환되는 값 종류를 이해할 수 있습니다.
하나의 기능 - 하나의 작업
함수는 이름에서 제안하는 대로 정확하게 수행해야 합니다.
두 개의 독립적인 작업은 일반적으로 함께 호출되더라도 일반적으로 두 개의 함수를 사용할 자격이 있습니다(이 경우 두 개를 호출하는 세 번째 함수를 만들 수 있습니다).
이 규칙을 위반하는 몇 가지 예는 다음과 같습니다.
getAge
– 나이와 함께 alert
를 표시하면 좋지 않습니다(가져오기만 해야 함).
createForm
– 문서를 수정하여 문서에 양식을 추가하면 좋지 않습니다(만들고 반환해야 함).
checkPermission
– access granted/denied
메시지를 표시하면 좋지 않습니다(확인만 수행하고 결과를 반환해야 함).
이러한 예에서는 접두사의 일반적인 의미를 가정합니다. 귀하와 귀하의 팀은 다른 의미에 대해 자유롭게 동의할 수 있지만 일반적으로 크게 다르지 않습니다. 어떤 경우든 접두사가 무엇을 의미하는지, 접두사가 붙은 함수가 무엇을 할 수 있고 무엇을 할 수 없는지 확실히 이해해야 합니다. 동일한 접두사가 붙은 모든 함수는 규칙을 따라야 합니다. 그리고 팀은 지식을 공유해야 합니다.
초단축 함수 이름
매우 자주 사용되는 함수에는 때때로 매우 짧은 이름이 있습니다.
예를 들어 jQuery 프레임워크는 $
사용하여 함수를 정의합니다. Lodash 라이브러리에는 _
라는 핵심 기능이 있습니다.
이는 예외입니다. 일반적으로 함수 이름은 간결하고 설명적이어야 합니다.
함수는 짧아야 하며 정확히 한 가지 일을 해야 합니다. 그 일이 크다면, 그 기능을 몇 개의 더 작은 기능으로 나누는 것이 가치가 있을 것입니다. 때로는 이 규칙을 따르는 것이 쉽지 않을 수도 있지만 확실히 좋은 일입니다.
별도의 함수는 테스트 및 디버깅이 더 쉬울 뿐만 아니라 그 존재 자체가 훌륭한 설명입니다!
예를 들어 아래의 두 함수 showPrimes(n)
비교해 보세요. 각각은 최대 n
까지 소수를 출력합니다.
첫 번째 변형은 라벨을 사용합니다.
함수 showPrimes(n) { nextPrime: for (let i = 2; i < n; i++) { for (let j = 2; j < i; j++) { if (i % j == 0) nextPrime을 계속합니다; } 경고(i); // 소수 } }
두 번째 변형은 추가 함수 isPrime(n)
사용하여 소수성을 테스트합니다.
함수 showPrimes(n) { for (let i = 2; i < n; i++) { if (!isPrime(i)) 계속; 경고(i); // 소수 } } 함수 isPrime(n) { for (let i = 2; i < n; i++) { if (n % i == 0) false를 반환합니다. } 사실을 반환; }
두 번째 변형은 이해하기 더 쉽습니다. 그렇죠? 코드 조각 대신 작업 이름( isPrime
)이 표시됩니다. 때때로 사람들은 이러한 코드를 자기 설명적이 라고 부릅니다.
따라서 함수를 재사용할 의도가 없더라도 함수를 생성할 수 있습니다. 코드를 구조화하고 읽기 쉽게 만듭니다.
함수 선언은 다음과 같습니다.
함수 이름(매개변수, 구분, 기준, 쉼표) { /* 코드 */ }
매개변수로 함수에 전달된 값은 해당 지역 변수에 복사됩니다.
함수는 외부 변수에 접근할 수 있습니다. 그러나 그것은 내부에서만 작동합니다. 함수 외부의 코드에는 지역 변수가 표시되지 않습니다.
함수는 값을 반환할 수 있습니다. 그렇지 않은 경우 결과는 undefined
입니다.
코드를 깔끔하고 이해하기 쉽게 만들려면 함수 내에서는 외부 변수가 아닌 지역 변수와 매개변수를 주로 사용하는 것이 좋습니다.
매개변수를 가져오지 않고 외부 변수를 부작용으로 수정하는 함수보다 매개변수를 가져와서 작업하고 결과를 반환하는 함수를 이해하는 것이 항상 더 쉽습니다.
함수 이름:
이름은 함수가 수행하는 작업을 명확하게 설명해야 합니다. 코드에서 함수 호출을 볼 때 좋은 이름을 사용하면 해당 함수가 수행하고 반환하는 작업을 즉시 이해할 수 있습니다.
함수는 동작이므로 함수 이름은 일반적으로 언어적입니다.
create…
, show…
, get…
, check…
등과 같은 잘 알려진 함수 접두사가 많이 있습니다. 함수가 수행하는 작업을 암시하는 데 사용하세요.
함수는 스크립트의 주요 구성 요소입니다. 이제 기본 사항을 다루었으므로 실제로 만들고 사용할 수 있습니다. 그러나 그것은 길의 시작일 뿐이다. 우리는 이들에 대해 여러 번 돌아와서 고급 기능에 대해 더 깊이 알아볼 것입니다.
중요도: 4
다음 함수는 매개변수 age
18
보다 큰 경우 true
반환합니다.
그렇지 않으면 확인을 요청하고 결과를 반환합니다.
함수 checkAge(나이) { if (나이 > 18) { 사실을 반환; } 또 다른 { // ... return verify('부모님이 허락하셨나요?'); } }
else
를 제거하면 기능이 다르게 작동하나요?
함수 checkAge(나이) { if (나이 > 18) { 사실을 반환; } // ... return verify('부모님이 허락하셨나요?'); }
이 두 변종의 동작에 차이가 있나요?
차이가 없습니다!
두 경우 모두 return confirm('Did parents allow you?')
if
조건이 거짓일 때 정확하게 실행됩니다.
중요도: 4
다음 함수는 매개변수 age
18
보다 큰 경우 true
반환합니다.
그렇지 않으면 확인을 요청하고 결과를 반환합니다.
함수 checkAge(나이) { if (나이 > 18) { 사실을 반환; } 또 다른 { return verify('부모님이 허락하셨나요?'); } }
if
없이 동일한 작업을 수행하려면 한 줄로 다시 작성하세요.
checkAge
의 두 가지 변형을 만듭니다.
물음표 연산자를 사용합니까 ?
OR ||
사용
물음표 연산자 '?'
사용 :
함수 checkAge(나이) { 복귀(18세 이상) ? true : verify('부모님이 허락하셨나요?'); }
OR ||
사용 (가장 짧은 변형):
함수 checkAge(나이) { 복귀(나이 > 18) || verify('부모님께서 허락하셨나요?'); }
여기서는 age > 18
괄호가 필요하지 않습니다. 더 나은 가독성을 위해 존재합니다.
중요도: 1
두 숫자 a
와 b
중 가장 작은 숫자를 반환하는 함수 min(a,b)
를 작성하세요.
예를 들어:
최소(2, 5) == 2 최소(3, -1) == -1 최소(1, 1) == 1
if
사용하는 솔루션 :
함수 min(a, b) { 만약 (a < b) { 반환하다; } 또 다른 { b를 반환; } }
물음표 연산자 '?'
를 사용한 솔루션 :
함수 min(a, b) { 반환 a < b ? a : b; }
PS 평등 a == b
의 경우 무엇을 반환할지는 중요하지 않습니다.
중요도: 4
x
n
제곱으로 반환하는 함수 pow(x,n)
작성하세요. 즉, x
n
번 곱하고 그 결과를 반환합니다.
pow(3, 2) = 3 * 3 = 9 pow(3, 3) = 3 * 3 * 3 = 27 pow(1, 100) = 1 * 1 * ...* 1 = 1
x
및 n
을 묻는 웹 페이지를 만든 다음 pow(x,n)
의 결과를 표시합니다.
데모 실행
PS 이 작업에서 함수는 n
의 자연값( 1
부터 최대 정수)만 지원해야 합니다.
함수 pow(x, n) { 결과 = x로 두십시오; for (let i = 1; i < n; i++) { 결과 *= x; } 결과 반환; } let x = 프롬프트("x?", ''); let n = 프롬프트("n?", ''); 만약 (n < 1) { Alert(`Power ${n}은 지원되지 않습니다. 양의 정수를 사용하세요`); } 또 다른 { 경고( pow(x, n) ); }