js 는 procedure language 에 가깝다. 그리고 procedure language 는 함수가 굉장히 중요한 역할을 담당한다. js 에도 class 가 추가되었는데, 그렇다면 object oriented language 가 아닌 것인가?

js 에 추가된 class 는 pure한 object oriented 가 아니고, prototype을 base로 한 가짜의 object oriented 이다. 그렇기 때문에 js 에서 function 은 매우 중요하다.

function 은 때로는 sub-program 이라고 부른다.

//Function
// - fundmental building block in the program 기본
// - subprogram can be used multiple times 여러번
// - perform a task or caculated a value 개선 또는 계산

// 1. Function declaration-
// function name(param1, param2) {body... return;}
// one function === one things
// 한가지의 동작만...
// a function declaration can be called earlier than it is defined. (hoisted)
// 정의 되지도 않은 함수를 미리 호출하는 것이 가능하다.
// function is object in JS

function printHello() {
    console.log(`Hello`);
}

printHello();

function log(message) { // 무엇을 전달 해야 하는지 정확하지 않다. 
    console.log(message); // type-script 를 배워야 하는 이유
}

log(`Hello`);

// 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); // name: "coder" 로 바뀐 것 확인 가능하다.

// 3. Default parameters (added in ES6)
function showMessage(message = 'malza', from) {
    console.log(`${message} by ${from}`); // malza by undefined
}

showMessage();

// 4. Rest parameters (added in ES6)
function  printAll(...args) { // array 형태로 전달된다.
    for(let i = 0; i < args.length; i++)
    {
        console.log(args[i]);
    }

    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  printfMessage() {
    let message = 'hello';
    console.log(message);
    console.log(globalMessage);

    function anotherPrint() {
        console.log(message);
        let childMessage = 'child';
    }
    //console.log(childMessage); // error!
    //이렇게 함수안에 함수, 중첩된 상태에서
    //자식의 함수가 부모함수의 변수에 접근이 가능한 것들을
    //closure 라고 한다. 이후에 다룬다.

    //return undefined; 생략되어 있는 것이다. return 이 없는 함수에 있다.
}

printfMessage();

// 6. Return a value
function sum(a, b) {
    return a + b;
}

const resutl = sum(1, 2);

// 7. Early return , early exit
// bad

function upgradeUser(user) {
    if(user.point > 10){
        //logic ~~~
    }    
}

//good
function upgradeUser(user) {
    if(user.point <= 10) {
        return;
    }
    //logic ~~~
}

// Function expression
// a function expression is created when the execution reached it.
// 미리 호출이 불가하다.

//다음과 같은 function expression 은 미리 호출이 안된다는 뜻이다.
const print = function () { // anonymouse function (function 이름이 없다.)
    console.log('print');
}

print();
const printAgain = print;
printAgain();
const sumAgain = sum;
console.log(sumAgain(1, 3));

// 2. Callback function using function expression
function randomQize(answer, printYes, printNo) {
    if(answer === 'love you') {
        printYes();
    }else {
        printNo();
    }
}

// anonymous function
const printYes = function() {
    console.log('yes!');
}

// named function
// better debugging in debugger's stack traces
// recursions
const printNo = function print() { // 디버깅 시에 이름을 띄우기 위함이다.
    console.log('No!');
}

randomQize('wrong', printYes, printNo);
randomQize('love you', printYes, printNo);

// Arrow function
// always anonymous
// 간결해진다.

// const simplePrint = function () {
//     console.log('simplePrint!');
// }

const simplePrint = () => console.log('simplePrint!');
const add = (a, b) => a + b;
const add2 = (a, b) => {
    // .........
    //~~~~~~~
    return a + b;
}

// IIFE : immediately Invoked Function Expression
// 즉시 함수 호출
(function hello(params) {
    console.log('IIFE');
}) ();
// 선언하자마자 호출하고 싶다면 ()로 감싸주고, (); 해주면 된다.
함수 선언문 vs 함수 표현식 정리

함수 선언문
// 어디서든지 호출 할 수 있다. 호이스팅 되기 때문이다.
sayHello();

function sayHello() {
	console.log('Hello');
}

함수 표현식
// 코드에 실제로 도달하면 생성.
let sayHello = function(){
	console.log('Hello');
}