// Function
// - fundamental building block in the program
// - subprogram can be used multiple times
// - performs a task or calculates a value
1. Function declaration
/* function name(param1, param2) {body... return}
one function === one thing
naming: doSomething, command, verb
e.g. createCardAndPoint -> createCard, createPoint
function is object in JS */
function printHello() {
console.log('Hello');
}
printHello();
/* Hello만 출력할 수 있으므로 활용도가 낮음 */
function log(message) {
console.log(message);
}
log('Hello@');
log('this is my test');
log(1234);
// log함수를 호출하면서 원하는 메시지는 뭐든 출력할 수 있음
2. Parameters
/* premitive parameters: passed by value
object parameters: passed by reference */
function changeName(obj) {
obj.name='coder';
}
const ellie={name: 'ellie'}; /*ellie라는 오브젝트를 만들어서 할당해주면 레퍼런스가 메모리에 들어가게 되고, 레퍼런스는 이 오브젝트를 메모리 어딘가에 가리킴(?) */
changeName(ellie); /* changeName 엘리를 전달하게 되면, obj.name에 따라 엘리를 coder로 변경하게 됨 */
console.log(ellie); /* 그래서 이렇게 콘솔로그로 출력할 때 coder로 변경되어 나옴 */
3. Default parameters (added in ES6)
function showMessage(message, from) {
console.log(`${message} by ${from}`);
}
showMessage('Hi!'); /* 여기까지 쓰면 message는 출력이 잘 되지만, from이 정의되어 있지 않으므로 'undefined'라고 뜸 */
/* 그래서 if절을 넣어서 unknown으로 출력되도록 함 */
function showMessage(message, from) {
if (from === undefined) {
from = 'unknown';
}
console.log(`${message} by ${from}`);
}
showMessage('Hi!');
/* 라고 기껏 필기했더니 '굳이 귀찮게 이렇게 할 필요 없다'라고 하심 */
/* 그래서 나온 것 */
function showMessage(message, from = 'unknown') {
console.log(`${message} by ${from}`);
}
showMessage('Hi!');
/* parameter 옆에 원하는 디폴트값을 지정해놓으면, 사용자가 parameter를 전달하지 않을 때 이 값으로 대체되어 출력됨 */
4. Rest parameters (added in ES6)
function printAll(...args) /* 이렇게 닷닷닷(...)을 놓으면 레스트파라미터라고 불리는데, 이것은 배열형태로 전달됨 (이런 게 있다-정도로) */
{
for (let i=0; i<args.length; i++) {
console.log(args[i]);
}
/* 간단하게 for - of를 이용해서 출력할 수도 있음 */
for (const arg of args) {
console.log(arg);
}
/* 더 간단하게 하고 싶다면(나중에 다시 배울 것) */
args.forEach((arg) => console.log(arg));
}
printAll('dream', 'coding', 'ellie');
5. Local scope
let globalMessage='global'; /* global variable */
function printMessage() {
let message='hello';
console.log(message); /* local variable */
console.log(globalMessage);
}
printMessage();
/* '밖에서는 안이 보이지 않고 안에서만 밖을 볼 수 있다'
블럭 안에서 변수를 선언하면 이것은 '지역 변수'임. 안에서만 접근이 가능하고, 이 메시지를 밖에서 출력하면 에러가 발생함.
하지만, 안에서는 이 globalMessage라는 것을 볼 수 있고 출력이 가능한 것을 확인할 수 있음. 이게 바로 scope이다.*/
let globalMessage='global'; /* global variable */
function printMessage() {
let message='hello';
console.log(message); /* local variable */
console.log(globalMessage);
function printAnother() {
console.log(message);
let childMessage='Hello'; /* 이 자식은 부모에게서 정의된 메시지들을 확인할 수 있음. 하지만 자식 안에 정의된 차일드메시지를 부모(상위)에서 보려고 하면, 에러가 발생함. */
}
}
printMessage();
6. Return a value
function sum(a, b) {
return a+b;
}
const result=sum(1, 2); /* 3이 리턴되는 것을 확인 가능 */
console.log(`sum: ${sum(1, 2)}`);
7. Early return, early exit
// bad ex.
function upgradeUser(user) {
if (user.point>10) /* (유저 포인트가 10 넘을 때 ~한다) */
{
/* long upgrade logic... */
/* 가독성이 떨어진다 */
}
}
// good ex.
function upgradeUser(user) {
if (user.point<=10) /* (조건이 맞지 않을 때에만,) */
{
return; /* (리턴하여 함수를 종료한다) */
}
/* long upgrade logic... */
}
// 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
1. Function expression
/* a function declaration can be called earlier than it is defined. (hoisted)
a functino expression is created when the execution reaches it. */
const print=function() { /* function함수를 선언함과 동시에 바로 print라는 변수에 할당하는 것 확인 가능. function에 아무런 이름이 없고(), function이라는 키워드를 통해 parameter와 block을 이용함. 이렇게 이름 없는 함수를 anonymous function이라 함. */
console.log('print');
};
print();
const printAgain=print; /* 다시 다른 변수에 또 할당하게 되면, 결국 이 printAgain은 함수를 가리키고 있기 떄문에... */
printAgain(); /* print가 출력되는 것을 볼 수 있음. */
const sumAgain=sum; /* sum이라는 functions을 윗부분 어딘가에서 정한 적이 있는데ㅎ 이를 sumAgain에 할당하게 되면, */
console.log(sumAgain(1,3)); /* 이렇게 동일하게 호출할 수 있음. */
2. Callback functino using function expression
function randomQuiz(answer, printYes, printNo) {
if (answer === 'love you') {
printYes();
} else {
printNo();
}
}
const printYes=function() { /* 이름 없는 anonymous function */
console.log('yes!');
};
const printNo=function print() { /* 이름 있는 named function */
console.log('no!');
};
randomQuiz('wrong', printYes, printNo);
randomQuiz('love you', printYes, printNo);
/* Arrow function
always anonymous */
const simplePrint=function() {
console.log('simplePrint!');
};
/*
const simplePrint=() => console.log('simplePrint!');
// function 키워드, block 필요없음. 한 줄에 묶어 arrow(=>)로 표기하면 끝!
*/
const add=(a,b)=>a+b;
/* 이것을 풀어 쓰면 다음과 같음
const add=function(a,b) {
return a+b;
}
*/
const simpleMultiply=(a,b)=>{
/* do something more */
return a*b;
};
/* IIFE: Immediately Invoked Function Expression */
/*
function hello() {
console.log('IIFE');
}
라는 함수를 호출하고 싶을 때, 이들을 ()로 묶고 바로 ();로 호출해주면 됨. 아래처럼 */
(function hello() {
console.log('IIFE');
})();
// expected output: IIFE