* Function
- 기본적인 빌딩블럭
- subprogram이라고도 불리며 여러번 재 사용이 가능하다.
- 한가지의 task(작업)나 값을 계산하기 위해 쓰인다.
1. Function declaration (함수 선언)
- function 키워드 이용, 이름(name)지정, ( )에 parameter(인자) 나열, { } body 로직 작성, return해주면 된다.
- 하나의 함수는 한 가지의 일만 한다.
- 함수이름 작성시, 동사형태로 이름을 지정해야한다.
ex)
createCardAndPoint 라는 함수 이름이 있다고 보자.
우린 이것을 creteCard 혹은 createPoint로 나눠야 할지 말지에 대해 고민해야한다.
- 함수는 object이다.
ex)
function printHello() {
console.log('Hello');
} --->함수 지정
printHello(); --->함수 호출
- log함수 호출하면 원하는 메세지 출력 가능.
ex)
log('Hello@');
- JS에서는 type이 없어서 숫자인지 string을 전달해야하는지 명확X. (만든사람이 대충만들어서)
그래서 사용하는 사람이 숫자로 전달할 수 있음.
ex)
log(1234);
- 숫자가 문자열로 변환돼서 로그가 출력되기때문에 상관없지만 다른 함수에서 타입이 중요한 경우 JS는 난해할 수 있다.
* TS(TypeScript) : 규모 있는 프로젝트, 작성한 것을 library 형태로 api로 제공할땐 TS를 사용하는 게 좋다. (함수의 interface만 봐도 무엇을 의미하는지 확실하게 확인하고 쓸 수 있기 때문이다. JavaScript에서는 명시X) : parameter이나 type을 명시하도록 돼있다. |
2. Parameter (매개변수)
// 2. Parameters
// premitive parameters: passed by value
// object parameters: passed by reference
function changeName(obj) {
obj.name = 'coder';
}
const ellie = { name: 'ellie'};
changeName(ellie);
console.log(ellie);
- premitive: 메모리에 value가 저장
- object: 메모리에 referece가 저장
- changeName()은 전달된 obj의 이름을 coder로 변경하는 함수.
ellie라는 const 정의 후 ellie라는 obj를 만들어 할당하면
메모리에는 obj가 만들어지 ref가 메모리에 들어감. 이 ref는는 이 obj를 메모리 어딘가에 가리키고 있다
obj는 ref로 전달되기 때문에 함수 안에서 obj의 값을 변경하게되면
그 변경된 사항이 그대로 메모리에 적용 되기에 추후에 변경된 사항들이 확인 가능하다.
3.Default parameters
- function을 실행했을 때 parameter값을 실수로 안넣거나 했을 경우를 대비해 parameter의 기본값(default값)을 설정할 수 있다.
- default parameter 선언은 등호(=)를 사용하면 된다.
- 그러면 function 실행시 parameter가 정의되지 않았을 때 default parameter가 발동된다.
- default parameter는 단순한 값 뿐만 아니라 연산자, 함수 등을 이용해 다양하게 설정할 수 있다.
: showMessage에 두 가지 parameters (message, from)이 있다. 그래서 이 message가 누구로부터 왔는지(from) 출력.
: (맨 아래) showMessage 호출할 때 ('Hi!')라는 메세지만 전달되는 것 확인할 수 있다. 메시지는 출력되지만 from이 정의되지 않아undefined로 나온다.
===> Hi 라는 하나의 인자만 전달되었고, 2번재 인자는 from에 대해서 그 어떤 것도 전달되지 않았기 때문에
- parameter값이 정의되지 않을 경우,
if (from === undefined) {
from = 'unknown';
}
(그 중 이부분)
- 예전엔 from이 undefined이면 unknown이라는 기본적인 string을 추가하자 라고 해서 unknown이라고 출력되는 것을 확인할 수 있었다.
- 하지만 지금은 이렇게 적지 않아도
function showMessage(message, from = 'unknown') {
console.log(`${message} by ${from}`);
}
이라고 지정하면 사용자가 parameter를 전달하지 않을때 이 값(unknown)이 대체되어 사용된다.
4. Rest parameters (added in ES6)
: 말 그대로 rest(여분, 나머지) parameter라는 의미.
: . . .을 사용한다.
:배열 형태로 전달
// 4. rest parameters (added in ES6)
function printAll(...args) {
for (let i = 0; i < args.length;) i++) {
console.log(args [i]);
}
}
printAll('dream', 'coding', 'ellie');
- printAll이라는 함수를 호출할 때 3개의 인자(dream, coding, ellie)를 전달한다.
- . . . args = 3개의 값이 담겨져있는 배열.
- for문 이용해서 "처음부터 arg의 갯수만큼 돌면서
1번째 인자(dream), 그 다음에는
2번째 인자(coding), 그 다음엔
3번째 인자(ellie) 를 출력한다.
===> for문을 통해 모든 요소를 출력해도 되고 그 외 다른 형태로도 출력 가능하다.
-<배열 출력하는 법>
: for이용해도 되지만 for .. of라는 문법으로 더 간단하게 할 수 있다.
for (const arg of args) {
console.log(arg);
}
- args에 있는 게 하나씩 지정되면서 log(arg)를 출력하게 되는 것.
- 더 간단한 방법으로는 forEach라는 함수형 언어를 이용해 출력가능하다. 더 자세한 건 배열공부하기
args.forEach((arg) => console.log(arg));
5. Local Scope (지역변수)
- 원리: 밖에서는 안이 보이지 않고 안에서만 밖을 볼 수 있다.
// 5. Local scope
let globalMessage = 'global'; // global variable
function printMessage() {
let message = 'hello';
console.log(message); // local variable
console.log(globalMessage);
}
printMessage();
scope에는 2가지가 있다.
1. Global scope
2. Local scope
: 블럭{ } 안에서 변수 선언하는 것 = local varialbe (지역변수)
: 블럭 { }안에서만 접근 가능
: { }블럭 밖에서 밖에서 메시지를 출력하게 되면 에러발생.
ex)
- console.log(message); 출력시 우측 콘솔에서 에러 발생.
- printMessage() 라는 함수 안에 printAnother() 이라는 함수가 또 있다.
- 자식은 부모에게서 정의된 메시지 확인할 수 있다.
- 하지만 자식 안에 정의된 childMessage를 부모에게서 보려고 한다면 에러가 날 것.
: 자식의 함수가 부모함수에 정의된 변수들로 접근 가능하다.
6. Return a value
: return: 어떤 함수를 사용하고나서 return을 쓰면 그자리에 return에 할당한 값을 그대로 출력하고 해당 함수를 종료한다.
// 6. Return a value
function sum(a, b) {
return a + b;
}
const result = sum(1, 2); //3
console.log(`sum: ${sum(1, 2)}`);
: sum이라는 함수 호출 시 1과 2를 합한 값인 3이 return됨
- return타입이 없는 함수들은 return undefined이 들어있는 것과 똑같다.
7. Early return, early exit
// 7. Early return, early exit
// bad
function upgradeUser(user) {
if (user.point > 10) {
//long upgrade logic...
}
}
- upgradeUser함수 안에서 user.point가 10이상일 때 진행하는 로직이 있다고 한다면 if 블럭 { }안에서 로직 작성시 가독성이 떨어진다. 이럴 경우 if와 else를 번갈아서 쓰는 것 보다는
//good
function upgreadeUser(user) {
if (user.point <= 10) {
return;
}
// long upgrade logic...
}
- 조건이 맞지 않을 땐 빨리 return해서 함수를 종료하고 조건 맞을때만 그 다음에 필요한 logic을 작성하는 게 좋다.
- 조건이 맞지 않은 경우 / 값이 undefined인 경우 / 값이 -1인 경우 빨리 return하기.
Function Expression (함수 표현)
// First-class function
// functions are treated like any other variable
// can be assigned as a value to variable
// can be passed as an argument to other functions.
// can be returned by another function
<복습>
- first-class function은 다른 함수와 마찬가지로
변수에 할당이 되고
function의 parameter로 전달
return값으로도 return된다.
1. Function expression (함수표현)
// 1. Function expression
// a function declaration can be called earlier than it is defined. (hoisted)
// a function expression is created when the execution reaches it.
const print = function () {
console.log('print');
};
print();
const printAgain = print;
printAgain();
const sumAgain = sum;
console.log(sumAgain(1, 3));
- function() 에 이름이 없고, function을 이용해 parameter와 { }블럭 이용한 것을 볼 수 있다.
함수에 이름이 없는 것을 anonymous function이라고한다.
- 함수의 이름 없이 필요한 부분( console.log('print'); )만 작성해서 할당할 수 있고
함수 이름을 작성할 수도 있다. = named function
ex)
const print = function print() { }
- 함수를 print에 할당하면 print라는 변수에 함수를 호출하듯 (); 로 호출하면 바로 프린트 출력됨.
-다시 다른 변수 (const printAgain)에 할당하게 되면
printAgain은 function을 가리키고 있으므로
printAgain(); 의 값은 print로 출력되는 것을 알 수 있다.
- (아까 위에서 sum이라는 함수 만들었음)
이것도 sumAgain이라는 변수를 할당하게 되면 동일하게 호출할 수 있다.
📍Function declaration 과 Function expression 차이점
- function expression
: 할당된 다음 부터 호출 가능
- Function declaration
: hoisting된다. (function이 선언되기 이전에 호출해도 뒤에서 sum이라는 함수를 정의하기 전에 JS엔진이 선언된 것을 제일 위로 올려주기 때문이다.
2. Callback function using function expreession
* Callback(콜백): 은 다른 코드의 인수로서 넘겨주는 실행 가능한 코드(함수로 생각하면 쉽다!)를 의미한다.
즉, 인수로 넘겨주는 코드를 Callback이라고 부른다!
📍callback function이란 무엇일까?
: 다른 코드(함수)의 인수로서 넘겨주는 함수를 의미!
- 사용하는 이유: 프로그램이 비순차적으로 실행됐을 때 사용
// 2. Callback function using function expreession
function randomQuiz(answer, printYes, printNo) {
if (answer === 'love you') {
printYes();
} else {
printNo();
}
}
- answer : 정답
- printYes : 정답일 때
- printNo : 정답이 아닐 때
상황에 맞을 때 전달된 함수(printYes, printNo) 를 부르는 것 = callback function
즉, 두 가지의 callback functions가 parameter로 전달돼서 answer이 love you인 경우에만
printYes라는 콜백함수를 호출, 아닐경우 printNo라는 콜백함수 호출함.
const printYes = function() {
console.log('yes!');
};
const printNo = functino print() {
console.log('no!');
};
randomQuiz('wrong', printYes, printNo);
randomQuiz('love you', printYes, printNo);
- printYes라는 변수에 yes를 출력하는 함수(function())를 할당하고
printNo라는 변수에는 no를 출력하는 함수((function print())가 온다.
- randomQuiz호출할 때 차례대로 정답, yes콜백함수, no콜백함수 출력.
- 이름 없는 함수 = anonymous function
// anonymous function
const printYes = function() {
console.log('yes!');
};
- named function
// named function
// better debuffing in debugger's stack traces
// recursions
const printNo = function print() {
console.log('no!');
};
: 함수의 이름: print
📍이름 쓰는 이유
: 디버깅할때 쓰임
: 함수 안에서 또 다른 함수를 호출할 때 쓰임( =recursions),
: 반복되는 평균값 계산 등 쓰임새가 다양하다.
===>알아만두기
-함수를 무한대로 호출하면 call stack이 꽉 찼다는 에러가 발생한다.
===>알아만두기
Arrow Function
: 함수를 간결하게 만들어준다.
: 항상 이름이 없는 anonymous function.
// Arrow function
// always anonymous
const simplePrint = function () {
console.log('simplePrint!');
};
- 문제점: function () { } 괄호 중괄호를 반복적으로 써줘야한다.
const simplePrint = () => console.log('simplePrint!');
- 저 위에 코드를 이렇게 줄일 수 있음.
또 다른 예시를 보자
// 1번
const add = (a, b) => a + b;
//2번
const add = function (a, b) {
return a + b;
}
1번과 2번 중 어떤 것이 더 간결해 보이는가?
1번이다.
복잡한 코드를 만들 때 블럭이 필요하다면, 이런식으로 블럭을 넣을 수가 있다.
const simpleMultiply = (a, b) => {
// do something more
return a * b;
}
- 블럭 쓰면 return키워드 써서 return 해야한다.
IIFE
: 함수 선언하면 나중에 호출을 해줘야한다. 선언과 동시에 호출할 수 있는 방법.
: 최근에는 잘 쓰이지는 않음.
// IIFE: Immediately Invoked Function Expression
function hello(){
console.log('IIFE');
}
'JavaScript' 카테고리의 다른 글
[JS] DOM이란? #2 부모, 자식, 형제 Node (0) | 2023.03.26 |
---|---|
[JS] DOM이란? #1 Node에 접근하는 방법 (0) | 2023.03.26 |
[JS] operator(연산자), if, switch, for loops 코드 (0) | 2023.03.13 |
[JS] 데이터타입, data types, 변수 선언 let vs var, hoisting (1) | 2023.03.12 |
[JS] 콘솔에 출력, script async 와 defer의 차이점 (0) | 2023.03.12 |