01. 선언적 함수

선언적 함수는 'function'이라는 예약어로 함수명을 명시하고, 함수 내용을 중괄호({ })로 감싸는 방식입니다.

say();      //함수가 호출되기 전에 선언
function say(){
    console.log("Hello, World!");
}
결과 확인하기

함수 이름을 지정하고 실행할 명령들을 묶는 것을 '함수를 선언한다'고 합니다.
그리고 이렇게 미리 선언해놓은 함수를 실행할 때는 '함수명( )'과 같이 함수 이름뒤에 소괄호'( )'를 붙여 사용합니다.
이걸 '함수를 호출한다'고 합니다.

웹 브라우저에서는 자바스크립트 소스를 해석할 때 변수나 함수 선언을 먼저 해석합니다.
때문에 앞에 쓰인 호출 선언은 변수나 함수를 선언하기 전에 해당 변수나 함수를 사용할 수 있는 것처럼 보이게 됩니다.
이런 자바스트립트 성질을 끌어올려 해석하는 것을 '호이스팅(Hoisting)'이라고 합니다.

02. 익명 함수

익명 함수는 변수에 함수를 저장하여 변수를 함수처럼 사용할 수 있도록 만들어줍니다.

let addNumbers = function(){
    let x = 2;
    let y = 3;
    let result = x + y;
    console.log(result);
}
addNumbers();		//변수를 호출하면 변수 안의 함수가 실행
결과 확인하기

익명 함수는 함수명이 없기 때문에 함수명을 생략하고, 해당 함수를 다른 변수에 할당하거나 다른 함수의 인수로 전달할 수 있습니다.
이 코드는 'addNumbers'라는 변수에 함수가 저장되어 있습니다.
변수를 호출하게 되면 변수 안의 함수가 실행이 되면서 마지막 console.log에서 구한 값을 호출하게 됩니다.

03. 매개변수 함수

함수를 선언할 때 사용되는, 외부에서 값을 받는 변수를 '매개변수parameter'라고 합니다.
함수가 호출될 때 넘기는 매개변수 값을 '인수argument'라고 합니다.

function allSum(n){
    let sum = 0;
    for(let i = 1; i <= n; i++){
    	sum = sum + i;	//sum += i
    }
    console.log(`1부터 ${n}까지 더하면 ${sum}입니다.`);
}
allSum(10);
결과 확인하기

매개변수는 함수의 소괄호'( )' 안에 매개변수의 이름을 넣고, 여러 개의 매개변수가 필요한 경우 쉼표' , '로 나열합니다.
매개변수는 어떤 값을 받느냐에 따라 함수의 다양한 결과를 보여주게 됩니다.
이렇게 하나의 함수를 여러 상황에서 사용하는 것을 '함수의 재사용성'이라고 합니다.

위의 코드는 인수에 어떤 숫자를 넣느냐에 따라 1부터 n까지 더하는 코드입니다.
함수가 호출되는 순서는 다음과 같습니다.

1. 함수를 호출하는 맨밑의 allSum( )에 인수 10이 들어갑니다.
2. 인수 10은 매개변수 n에 넘겨집니다.
3. 함수 안의 실행문이 진행되고 console.log에 n과 sum의 값이 들어갑니다.

04. 리턴 함수

'return'은 함수를 통해 처리된 결과를 반환시켜주는 명령어입니다.

function allSum(n){
    let sum = 0;
    for(let i = 1; i <= n; i++){
    	sum = sum + i;	//sum += i
    }
    return sum;
}

let num = parseInt(prompt("1부터 몇까지 더할까요?"));
console.log(`1부터 ${num}까지 더하면 ${allSum(num)}입니다.`);
//프롬프트 창을 안 띄우기 위해 num은 10으로 대입함.
결과 확인하기

function 함수명(){
실행문;
return 실행문 결과; //함수의 실행문 계산 값 //반환할 함수 내용
}
console.log(함수명()); //반환한 결과 호출

'함수명()'로 함수를 호출하게 되면 함수가 실행되면서 함수 안의 실행문이 실행됩니다.
예악어 'return'은 실행문을 마친 뒤의 결과를 호출한 곳으로 반환해주고 함수는 종료가 됩니다.
위의 코드는 매개변수 함수에서 사용했던 코드에 return을 추가한 코드입니다.
return을 추가하게 되면 allSum() 함수의 결과를 밖으로 넘겨줄 수 있게 되어 좀 더 자유롭게 사용할 수 있습니다.

05. 화살표 함수 : 선언적 함수

화살표 함수는 function 키워드를 생략하고 부등호 ' = '와 ' > '를 사용하여 표현합니다.

say = () => console.log("Hello, World!");
say();
결과 확인하기

화살표 함수는 ECMAScript 2015 (ES6)에 추가된 내용으로 ' => '를 이용하여 함수를 간결하게 표현할 때 사용합니다.
화살표 함수는 function 키워드를 생략하고 부등호 ' = '와 ' > '를 사용하여 표현합니다.
1. function을 지운다.
2. 함수명 또는 변수명과 (매개변수) 사이에 부등호 ' = ' 를 추가합니다.
3. (매개변수)와 중괄호({ }) 사이에 ' => '를 추가합니다.

06. 화살표 함수 : 익명 함수

익명 함수는 변수명을 남기고 화살표 함수 표기를 하면 된다.

let addNumbers = () => {
    let x = 2;
    let y = 3;
    let result = x + y;
    console.log(result);
}
addNumbers();
결과 확인하기

익명 함수를 화살표 함수로 표현할 때도 똑같이 function을 지우고 괄호와 변수 사이에 부등호를 넣는다.
변수 선언자 let을 지우면 선언적 함수 생략과 같은 모양으로 쓸 수 있다.

07. 화살표 함수 : 매개변수 함수

allSum = (n) => {
    let sum = 0;
    for(let i = 1; i <= n; i++){
    	sum = sum + i;	//sum += i
    }
    console.log(`1부터 ${n}까지 더하면 ${sum}입니다.`);
}
allSum(10);
결과 확인하기

08. 화살표 함수 : 리턴 함수

function allSum(n){
    let sum = 0;
    for(let i = 1; i <= n; i++){
    	sum = sum + i;	//sum += i
    }
    return sum;
}

let num = parseInt(prompt("1부터 몇까지 더할까요?"));
console.log(`1부터 ${num}까지 더하면 ${allSum(num)}입니다.`);
//프롬프트 창을 안 띄우기 위해 num은 10으로 대입함.
결과 확인하기

09. 화살표 함수 : 익명 함수 + 매개변수 + 리턴값

화살표 함수는 바로 알아보기 어려워서 변수로 자주 바꾼다.

const func = (str) => {
    return str;
}
document.write(func("실행되었습니다1"));
결과 확인하기

10. 화살표 함수 : 익명 함수 + 매개변수 + 리턴값 + 괄호 생략

함수명을 나타내는 괄호를 생략할 수 있다.

const func = str => {
    return str;
}
document.write(func("실행되었습니다2"));
결과 확인하기

11. 화살표 함수 : 익명 함수 + 매개변수 + 리턴값 + 괄호 생략 + 리턴 생략

함수 내용을 나타내는 중괄호와 리턴 명령어를 생략할 수 있다.

const func = str => str;
    document.write(func("실행되었습니다3"));
결과 확인하기

12. 화살표 함수 : 선언적 함수 + 매개변수 + 리턴값 + 괄호 생략 + 리턴 생략

변수 선언자를 생략하면 선언적 함수의 축약형을 만들 수 있다.

func = str => str;
    document.write(func("실행되었습니다4"));
결과 확인하기

너무 과한 축약은 오히려 알아보기 힘들 수 있으니 주의해야 한다.

13. 함수 유형 : 함수와 매개변수를 이용한 형태

매개변수를 여러 개 사용하여 재활용합니다.

function func(num, str1, str2){
    document.write(num + ". " + str1 + "가 " + str2 + "되었읍디다.<br>");
}

func("1", "함수", "실행");
func("2", "자바스크립트", "실행");
func("3", "리액트", "실행");    //매개변수를 여러 개 써서 재활용
결과 확인하기

매개변수를 활용하면 변수를 여러 개 쓰지 않고도 함수를 활용할 수 있다.

14. 함수 유형 : 함수와 변수를 이용한 형태

변수에 값을 할당하여 함수로 실행합니다.

function func(num, str1, str2){
    document.write(num + ". " + str1 + "가 " + str2 + "되었읍디다.
"); } const youNum1 = 1; const youNum2 = 2; const youNum3 = 3; const youStr1 = "함수"; const youStr2 = "자바스크립트"; const youStr3 = "리액트"; const youCom1 = "실행"; func(youNum1, youStr1, youCom1); func(youNum2, youStr2, youCom1); func(youNum3, youStr3, youCom1);
결과 확인하기

데이터를 저장한 변수를 매개변수로 활용하여 함수에 넣어서 실행합니다.

15. 함수 유형 : 함수와 배열을 이용한 형태

배열의 데이터를 함수에 넣어 실행합니다.

function func(num, str1, str2){
    document.write(num + ". " + str1 + "가 " + str2 + "되었읍디다.
"); } const num = [1,2,3]; const info = ["함수", "자바스크립트", "리액트", "실행"]; func(num[0], info[0], info[3]); func(num[1], info[1], info[3]); func(num[2], info[2], info[3]);
결과 확인하기

배열의 데이터를 하나의 매개변수로 활용해 함수를 실행할 수 있습니다.

16. 함수 유형 : 함수와 객체를 이용한 형태

객체의 데이터를 함수에 넣어 실행합니다.

function func(num, str1, str2){
    document.write(num + ". " + str1 + "가 " + str2 + "되었읍디다.
"); } const info = { num1 : 1, name1 : "함수", num2 : 2, name2 : "자바스크립트", num3 : 3, name3 : "리액트", word : "실행" } func(info.num1, info.name1, info.word); func(info.num2, info.name2, info.word); func(info.num3, info.name3, info.word);
결과 확인하기

변수 info에 들어있는 객체를 부르는 것으로 info.key를 이용합니다.
각각의 객체 데이터는 함수의 매개변수로 함수를 실행합니다.

17. 함수 유형 : 함수와 객체, 배열을 이용한 형태

배열 속의 객체 데이터를 이용하여 함수를 실행합니다.

function func(num, str1, str2){
    document.write(num + ". " + str1 + "가 " + str2 + "되었읍디다.
"); } const info = [ { num: 1, name: "함수", word: "실행" }, { num: 2, name: "자바스크립트", word: "실행" }, { num: 3, name: "리액트", word: "실행" } ] func(info[0].num, info[0].name, info[0].word); func(info[1].num, info[1].name, info[1].word); func(info[2].num, info[2].name, info[2].word);
결과 확인하기

배열 안에 있는 객체를 불러오기 위해 먼저 배열 호출([]) 뒤에 .객체명을 씁니다.
객체의 데이터가 함수의 매개변수로 활용되어 실행됩니다.

18. 함수 유형 : 객체 안에 함수를 이용한 형태

객체 데이터와 함께 들어있는 함수를 불러오는 방법입니다.

const info = {
    num1: 1,
    name1: "함수",
    num2: 2,
    name2: "자바스크립트",
    num3: 3,
    name3: "리액트",
    word: "실행",
    result1: function(){
        document.write(info.num1 + ". " + info.name1 + "가 " + info.word + "되었읍디다.
"); }, result2: function(){ document.write(info.num2 + ". " + info.name2 + "가 " + info.word + "되었읍디다.
"); }, result3: function(){ document.write(info.num3 + ". " + info.name3 + "가 " + info.word + "되었읍디다.
"); } } info.result1(); //info. 객체 먼저 부르고 result1()로 실행 info.result2(); info.result3();
결과 확인하기

객체 안에 함수가 들어있는 경우, "info."으로 객체를 먼저 호출합니다.
그다음 result()를 쓰고 안에 있는 함수를 실행합니다.

19. 함수 유형 : 객체생성자 함수

객체생성자 함수를 통해 함수식을 간결하게 표현합니다.

function Func(num, name, word){
    this.num = num;
    this.name = name;
    this.word = word;

    this.result = function(){
        document.write(this.num + ". " + this.name + "가 " + this.word + "되었읍디다.
"); } } //인스턴스 생성 new const info1 = new Func(1, "함수", "실행"); const info2 = new Func(2, "자바스크립트", "실행"); const info3 = new Func(3, "리액트", "실행"); info1.result(); info2.result(); info3.result();
결과 확인하기

생성자 함수 "Func"를 통해 info1~3 객체를 생성한 예시입니다.
생성자 함수는 다른 함수와 차이를 두기 위해 함수명의 첫 문자를 대문자로 표현합니다.
생성자 함수로 생성된 객체들은 생성자 함수에서 정의한 속성을 그대로 상속받습니다.
함수 안의 "this"는 함수를 통해 생성되는 객체를 의미합니다.

20. 함수 유형 : 프로토타입 함수

prototype을 이용하면 객체의 메서드를 생성자 함수 내에 정의하지 않고도 생성된 객체에서 호출하여 사용할 수 있습니다.

function Func(num, name, word){
    this.num = num;
    this.name = name;
    this.word = word;
}

//프로토타입 생성 // 지역변수인 this를 밖에서 쓸 수 있게 해줌
Func.prototype.result = function(){
    document.write(this.num + ". " + this.name + "가 " + this.word + "되었읍디다.
"); } const info1 = new Func(1, "함수", "실행"); const info2 = new Func(2, "자바스크립트", "실행"); const info3 = new Func(3, "리액트", "실행"); info1.result(); info2.result(); info3.result();
결과 확인하기

객체의 메서드의 경우 다른 속성처럼 값의 변화가 없기 때문에 불필요하게 상속시켜 메모리를 낭비할 필요가 없습니다. prototype을 이용하면 낭비 없이 호출하여 사용할 수 있습니다.

21. 함수 유형 : 객체 리터럴 함수

객체 리터럴 함수는 메서드를 직관적으로 관리할 수 있습니다.

function func(num, name, com){
    this.num = num;
    this.name = name;
    this.com = com;
}
func.prototype = {
    result1: function(){
        document.write(`${this.num}. ${this.name}가 ${this.com}되었습니다.
`); }, result2: function(){ document.write(`${this.num}. ${this.name}가 ${this.com}되었습니다.
`); }, result3: function(){ document.write(`${this.num}. ${this.name}가 ${this.com}되었습니다.
`); } } //인스턴스 const info1 = new func("102", "함수", "실행"); const info2 = new func("202", "자바스크립트", "실행"); const info3 = new func("302", "리액트", "실행"); //실행문 info1.result1(); info2.result2(); info3.result3();
결과 확인하기

이 방법은 코드의 가독성을 높일 수 있습니다. 메서드가 많아질수록 코드가 길어지기 때문에, 이를 객체 리터럴 형식으로 바로 정의하는 방법은 코드의 구조를 더욱 명확하게 만들어줄 수 있습니다. 또한, 프로토타입 객체에 메서드를 일일이 추가하는 방법과는 달리, 객체 리터럴 형식으로 바로 정의하기 때문에, 메서드를 추가하거나 수정할 때 더욱 직관적으로 코드를 작성할 수 있습니다.

22. 함수 유형 : 즉시 실행 함수

IIFE(Immediately Invoked Function Expression)는 즉시 실행되는 함수 표현식입니다. 함수를 정의하고 즉시 호출하는 것으로, 함수를 선언하면서 동시에 실행할 수 있습니다.

// function func(){
//     document.write("함수가 실행되었습니다람쥐");
// }
// func();

(function (){
    document.write("500. 함수가 실행되었습니다람쥐
"); })(); (() => { document.write("501. 함수가 실행되었습니다람쥐
"); })();
결과 확인하기

IIFE는 전역 스코프를 오염시키지 않고, 모듈화에 용이하게 사용됩니다. 전역 변수의 충돌을 피하고, 코드를 안전하게 유지하기 위해 사용됩니다.
IIFE는 다양한 방식으로 사용됩니다. 함수 내부에 변수를 선언하고, 이 변수를 반환하는 형태로 사용할 수 있습니다. 이를 통해 변수를 비공개(private)하게 유지할 수 있습니다.

23. 함수 유형 : 파라미터 함수

함수 정의에서 파라미터의 기본값을 지정할 수도 있습니다. 파라미터에 기본값을 지정하면, 함수가 호출될 때 해당 파라미터에 전달된 인수가 없는 경우 기본값이 사용됩니다.

// function func(str){
//     document.write(str);
// };
// func("600. 함수가 실행되었습니다.
"); function func(str = "600. 함수가 실행되었습니다.
"){ document.write(str); }; func();
결과 확인하기

예를 들어, 다음의 코드에서는 func() 함수를 정의할 때, str 파라미터의 기본값으로 "600. 함수가 실행되었습니다."를 지정했습니다.
함수의 파라미터에 기본값을 지정하면 함수 호출 시 인수를 생략할 수 있기 때문에 함수를 사용하기 더 편리해집니다.
또한, 기본값이 없는 파라미터는 함수 호출 시 인수가 생략되면 undefined가 전달되는데, 이를 방지하기 위해서도 파라미터의 기본값을 지정하는 것이 좋습니다.

24. 함수 유형 : 아규먼트 함수

JavaScript 함수에서 arguments는 함수에 전달된 모든 인수(argument)를 담고 있는 유사 배열 객체입니다.

// function func(str1, str2,){
//     document.write(str1);
//     document.write(str2);
// };
// func("함수 실행1", "함수 실행2");   //매개변수 함수

function func(str1, str2,){
    document.write(arguments[0]);
    document.write(arguments[1]);
};
func("함수 실행1", "함수 실행2
"); //매개변수 함수
결과 확인하기

arguments 객체의 각 인덱스에는 해당 인덱스에 대응하는 인수의 값이 저장됩니다.
arguments 객체를 사용하면 함수에 전달된 인수의 개수나 값을 동적으로 처리할 수 있습니다.

25. 함수 유형 : 재귀 함수

재귀함수(Recursive Function)는 자신을 호출하는 함수입니다.

// function func(num){
//     document.write(num);
// };
// func(10);

function func(num){
    if(num<=1){
        document.write("함수가 실행되었습니다.");
    } else {
        document.write("함수가 실행되었습니다.");
        func(num-1);
    }
};
func(10);   //여러 번 함수 실행이 필요할 때(for문처럼) 근데 과부하 걸려서 잘 안 씀

// function animation(){
//     document.write("애니메이션이 실행되었습네다");
//     requestAnimationFrame(animation);   //1초에 24번 반복하는 최적화 요즘 이거 씀
// }
// animation()
결과 확인하기

재귀함수는 기본적으로 두 가지 요소로 구성됩니다.
첫째, 자신을 호출하는 부분이 있어야 하며, 둘째, 종료 조건이 있어야 합니다.
종료 조건이 없으면 함수 호출이 무한히 반복되어 스택 오버플로우(Stack Overflow)가 발생할 수 있습니다.

26. 함수 유형 : 콜백 함수(다른 함수에 인수로 넘겨지는 함수)

콜백 함수(Callback Function)는 다른 함수의 인수로 전달되는 함수입니다.

// function func1(){
//     document.write("1. 햄수 실행");
// }
// function func2(){
//     document.write("2. 햄수 실행");
// }
// func1();
// func2();        //이러면 동시에 실행댐 ㄷㄷ

function func(){
    document.write("2. 햄수 실행");
}
function callback(str){
    document.write("1. 햄수 실행");
    str();
}
callback(func);     //1.이 먼저 실행된다. 메인 실행 먼저 하고 다음에 다른 기능 써야 할 때
결과 확인하기

콜백 함수를 사용하면, 함수의 실행 결과를 즉시 반환하지 않고, 함수가 실행되고 나서 콜백 함수가 호출될 때까지 대기할 수 있습니다. 이를 통해 복잡한 비동기 처리를 간단하게 처리할 수 있습니다.
콜백 함수는 호출 시점을 알 수 없는 비동기 처리(asynchronous processing)나 이벤트 처리(event handling) 등에 많이 사용됩니다.

27. 함수 유형 : 콜백 함수(반복문)

콜백 함수를 반복문에서 사용하면, 비동기 처리나 이벤트 처리와 같이 여러 번 함수를 호출해야 하는 경우 유용합니다.

function func(index){
    document.write("함수가 실행되었습니다" + index);
}
function callback(num){
    for(let i=1; i<=10; i++){
        num(i);
    }                
}
callback(func);
결과 확인하기

콜백 함수를 반복문에서 사용하는 방법은, 반복문 내에서 콜백 함수를 호출하는 것입니다. 이렇게 하면 반복문을 실행하면서 여러 번 콜백 함수가 호출됩니다.
특정 이벤트가 발생할 때마다 콜백 함수를 호출하는 경우, 반복문을 사용하여 여러 개의 이벤트를 처리할 수 있습니다.

28. 함수 유형 : 콜백 함수(동기/비동기)

콜백 함수를 사용하여 작업이 완료되면 호출되는 함수를 정의할 수 있습니다.

//01
function funcA(){
    console.log("funcA가 실행되었습니다.");
}
function funcB(){
    console.log("funcB가 실행되었습니다.");
}

funcA();
funcB();
// a 나오고 b 나오고

// 02
function funcA(){
    setTimeout(() => {
        console.log("funcA가 실행되었습니다.");
    }, 1000);
}
function funcB(){
    console.log("funcB가 실행되었습니다.");
}

funcA();
funcB();
// b가 먼저 나옴 ㅡㅡ

// 03
function funcA(callback){
    setTimeout(() => {
        console.log("funcA가 실행되었습니다.");
        callback();
    }, 1000);
}
function funcB(){
    console.log("funcB가 실행되었습니다.");
}
funcA(function(){
    funcB();
})
// a 먼저 실행됐음


// 콜백지옥 ㄷㄷ
function funcA(callback){
    setTimeout(() => {
        console.log("funcA가 실행되었습니다.");
        callback();
    }, 1000);
}
function funcB(callback){
    setTimeout(() => {
        console.log("funcB가 실행되었습니다.");
        callback();
    }, 1000);
}
function funcC(callback){
    setTimeout(() => {
        console.log("funcC가 실행되었습니다.");
        callback();
    }, 1000);
}
function funcD(){
    setTimeout(() => {
        console.log("funcD가 실행되었습니다.");
    }, 1000);
}
funcA(function(){
    funcB(function(){
        funcC(function(){
            funcD();
        })
    })
})
// 살려줘

콜백 함수는 주로 함수 내에서 비동기적으로 처리되는 작업이 완료된 후에 실행되는 코드를 작성할 때 사용됩니다.
예를 들어, funcA 함수에서는 비동기적으로 처리되는 작업이 완료된 후에 callback 함수를 호출하여, funcB 함수를 실행하도록 구현했습니다.
이렇게 하면, funcB 함수가 funcA 함수의 작업이 완료된 후에 실행되므로, 비동기 작업을 처리하면서도 순서를 유지할 수 있습니다.