JavaScript/Vanila JS

JavaScript 기초(4)- 함수, 객체, 프로토타입

두설날 2024. 4. 16. 16:30

*이 글을 읽기전에 작성자 개인의견이 있으니, 다른 블로그와 교차로 읽는것을 권장합니다.*

1. 사용자 정의 함수(function)

    - 하나의 특별한 목적의 작접을 수행하도록 설계된 독립적인 블록
    - 필요할 때마다 호출하여 해당 작업을 반복 수행할 수 있습니다.
    - 코드를 재활용하기 위한 목적

1-1. 함수 선언식
    function 함수명(매개변수1, 매개변수2 ..){
        함수가 호출되었을 때 실행할 문장;
        ...
        return 값;
    }


1-2. 함수 표현식
    const 변수명 = function(매개변수1, 매개변수2, ..){
        함수가 호출되었을 때 실행할 문장;
        ...
        return 값;
    }

1-3. 디폴트 매개변수
매개변수의 값을 설정하는 것
- 매개변수의 값을 정하지 않으면 기본값을 변수에 저장합니다.

    function 함수명(매개변수1=값1, 매개변수2=값2, ...){
        함수가 호출되었을 때 실행할 문장;
        ...
        return 값;
    }

1-4. 나머지 매개변수
- 생략 접두사(...)를 사용하여 특정 위치의 인수부터 마지막 인수까지 한번에 지정할 수 있습니다.

    funciton 함수명(매개변수1, ...매개변수2){
        함수가 호출되었을 때 실행할 문장;
        ...
        return 값
    }

    함수명(값1, 값2, 값3, 값4);

    매개변수1: 값1
    매개변수2: 값2, 값3, 값4

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>함수</title>
</head>
<body>
    <h2>함수</h2>
    <script>
        function func1(){
            console.log('func1() 호출!');
        }

        func1();

        console.log('--------');

        function func2(num){
            console.log(`전달받은 매개변수의 값: ${num}`);
        }
        
        func2(10);
        func1('apple');
        func2(true);
        func2();

        console.log('--------');

        function func3(start, end){
            let sum = 0;
            for(let i =start; i<=end; i++){
                sum += i
            }
            console.log(`${start}부터 ${end}까지의 총합: ${sum}`);
        }

        func3(1,100);
        func3(1); //1과 undefined 연산
        console.log('-----------');

        function func4(){
            return '🥩';
        }

        func4();
        console.log(func4());
        const presents =func4();
        console.log(presents);

        console.log('-----------');
        
        function func5(num1=1, num2=1){
            console.log(`num1의 값:${num1}, num2의 값:${num2}`);
            console.log(`${num1} * ${num2} = ${num1*num2}`);
        }

        func5(10,3);
        func5(10);
        func5();

        console.log('-----------');

        function func6(...x){
            console.log(`x의 값: ${x}`);
            console.log(`x의 타입: ${typeof(x)}`);

            for(i in x){
                console.log(`i의 값: ${i}, x[${i}]: ${x[i]}`);
            }
        }

        func6(30, 50, 80, 100, 40);
        func6(50, 80);

            // 보너스!
            (function(){
                console.log('함수를 만들고 바로 호출하기');
            })();

            // func7();

            // 함수 표현식
            const func7 = function(){
                console.log('func7() 호출!');
            }

            func7();
    </script>
</body>
</html>




 호이스팅(hoisting) : JavaScript에서 변수가 선언된 위치와 상관없이 함수나 코드 블록의 맨 위로 끌어올려지는 동작을 말합니다.
 - 인터프리터가 변수와 함수의 메모리 공간을 선언전에 할당하는 것입니다.
 - var로 선언한 변수의 경우 호이스팅 시 undefined로 변수를 초기화
 - let과 const로 선언한 변수의 경우 호이스팅 시 변수를 초기화하지 않습니다. 초기화 전에 접근하면 ReferenceError 발생합니다.


2. 화살표 함수

- function 키워드를 사용하여, 함수를 만드는 것보다 간단하게 표현하는 함수표현식입니다.
- 화살표 함수는 항상 익명입니다.
- return은 생략하며, 모든 화살표 함수return 형입니다.

매개변수가 없는 경우

 const 변수명 = function(){
        ...
    }
 const 변수명 = () => {
        ...
    }
    
const 변수명 = () => 문장;

매개변수가 있는 경우

const 변수명 = 매개변수1 =>{
        ...
    }

const 변수명 = ('매개변수1, 매개변수2 ...) =>{
        ...
    }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>화살표 함수</title>
</head>
<body>
    <h2>화살표 함수</h2>
    <script>
        const func1 = () => console.log('안녕하세요! 자바스크립트!');

        func1();

        console.log('---------');

        const func2 = x => x*x;
        const result = func2(10);
        console.log(`10의 제곱: ${result}`);

        const func3 = (x,y) => {
            let sum = 0;
            for(let i=x; i<=y; i++){
                sum += i;
            }
            return sum;
        }

        const total = func3(1,100);
        console.log(`1부터 100까지의 합: ${total}`);
35
        console.log('-----------');

        let age = Number(prompt('나이를 입력하세요'));
        const isAdult = (age>19) ? () => console.log('성인입니다') : () => console.log('미성년입니다!');

        isAdult();
    </script>
</body>
</html>


3. 객체(Object)

하나의 주제를 가지고 관련있는 프로퍼티(Property)를 가지고 있는 집합입니다.

프로퍼티(property)
- 이름과 값으로 구성된 정렬되지 않은 집합
- 프로퍼티는 함수도 저장할 수 있습니다. -> 프로퍼티 메서드

객체(Object): 프로그래밍에서 객체는 데이터와 이 데이터에 관련된 동작(메소드)을 포함하는 개념적인 컨테이너입니다. 객체는 키와 값으로 이루어진 속성들의 집합입니다. 속성(Property): 객체의 상태를 나타내는 값이며, 키-값(key-value) 쌍으로 구성됩니다. 각 속성은 객체의 특징이나 특성을 나타냅니다. 객체의 속성은 이름()과 그에 해당하는으로 구성되며, 이 값은 데이터일 수도 있고 함수일 수도 있습니다.


객체를 생성하는 방법
3-1. 리터럴 표기법

3-2. 생성자를 이용
- 객체를 만드는 함수입니다.
new 연산자를 사용하여, 객체를 생성하고 초기화할 수 있습니다.
- 같은 형태의 객체를 여러개 생성할 때 유리합니다.

function 함수명(매개변수1, 매개변수2, ..){
        this.프로퍼티1 = 값1;
        this.프로퍼티2 = 값2;
        ...
        this.프로퍼티n = function(){
            ...
        }
    }

    const 변수1 = new 함수명(값1, 값2, ...);
    const 변수2 = new 함수명(값1, 값2, ...);


3-3. 클래스 이용
- ECMA Script6(ES6)에 추가된 객체 생성 방법입니다.
- 내부적으로 생성자를 이용한 객체 생성 방법과 동일하게 작동합니다.

const 클래스명 = class{
        constructor(매개변수1, 매개변수2, ...){
            this.프로퍼티1 = 값1;
            this.프로퍼티2 = 값3;
            ...
        }

        메소드명(매개변수1, 매개변수2,..){
            ...
        }
    }

    const 변수1 = new 함수명(값1, 값2, ...);
    const 변수2 = new 함수명(값1, 값2, ...);
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>객체만들기</title>
</head>
<body>
    <h2>객체만들기</h2>
    <script>
        // 리터럴 표기법
        const Rucy = {
            name: '루시',
            age : 14,
            color: 'white',
            birthday: '20091210',
            getBirthday: function(){
                return this.birthday;
            }
        }

        console.log(Rucy.name);
        console.log(Rucy.age);
        console.log(Rucy.color);
        console.log(Rucy.birthday);
        console.log(Rucy.getBirthday);
        console.log(Rucy.getBirthday());

        console.log('------------');

        for(let i in Rucy){
            console.log(`i:${i}, Rucy[${i}]: ${Rucy[i]}`);
        }

        console.log('------------');

        // 생성자를 이용한 객체
        function Dog(name, color){
            this.name=name;
            this.color=color;
            this.eat=function(){
                return `${this.name}사료를 먹습니다`;
            }
        }

        const PPomi = new Dog('뽀미', '흰색');
        console.log(PPomi.name);
        console.log(PPomi.color);
        console.log(PPomi.eat);
        console.log(PPomi.eat());

        console.log('-------------');

        // 클래스를 이용한 객체 생성
        const Student = class {
            constructor(name, hp, age){
                this.name= name;
                this.hp = hp;
                this.age = age;
            }
            getName(){
                return `이름은 ${this.name} 입니다`;
            }
        }

        const apple = new Student('김사과','010-1111-1111', 20);
        console.log(apple.name);
        console.log(apple.hp);
        console.log(apple.age);
        console.log(apple.getName);
        console.log(apple.getName());
    </script>
</body>
</html>


4. 프로토타입(prototype)


 - 모든 객체는 프로토타입이라는 객체를 가지고 있습니다.
 - 모든 객체는 프로토타입으로부터 프로퍼티프로퍼티 메서드를 상속받습니다.
 - 모든 객체는 최소한 하나 이상의 다른 객체로부터 상속을 받으며 상속되는 정보를 제공하는 객체프로토타입이라고 합니다.

const dog = new Dog(); // Dog.prototype, Object.prototype
// new 연산자는 JavaScript에서 새로운 객체를 생성할 때 사용

상속
- 클래스 기반의 객체지향 언어와 다릅니다.
- 자바스크립트는 프로토타입 기반의 객체지향언어입니다.

프로토타입(Prototype)은 객체 지향 프로그래밍에서 객체의 원형(prototype object)을 나타내는 것입니다.

프로토타입의 동작 원리

JavaScript에서 객체는 다른 객체를 상속합니다. 이 상속은 프로토타입 체인(Prototype Chain)을 통해 이루어집니다. 모든 객체는 부모 역할을 하는 프로토타입 객체를 가지고 있습니다. 이 프로토타입 객체에서 속성이나 메소드를 찾지 못한 경우, JavaScript는 프로토타입 체인을 따라 상위 프로토타입으로 이동하여 검색합니다.
// 객체 생성
let animal = {
  type: "Dog",
  sound: "Woof!",
  makeSound: function() {
    console.log(this.sound);
  }
};

// animal을 상속받는 객체 생성
let myPet = Object.create(animal);
myPet.name = "Buddy";

// myPet에서 속성을 찾지 못한 경우 부모 객체로 이동하여 검색
console.log(myPet.type);      // Output: Dog
console.log(myPet.name);      // Output: Buddy
myPet.makeSound();            // Output: Woof!
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>프로토타입</title>
</head>
<body>
    <h2>프로토타입</h2>
    <script>
        function Dog(color, name, age){
            this.color = color;
            this.name = name;
            this.age = age;
        }

        const Rucy = new Dog('흰색', '루시', 14);
        console.log(Rucy);
        console.log(`이름: ${Rucy.name}`);
        console.log(`색상: ${Rucy.color}`);
        console.log(`나이: ${Rucy.age}`);
        Rucy.family = '포메라니안';
        Rucy.getFamily = function(){
            return this.family;
        }
        console.log(`종:${Rucy.family}`);
        console.log(`getFamily: ${Rucy.getFamily()}`);

        const PPomi = new Dog('흰색','뽀미',6);
        console.log(`이름: ${PPomi.name}`);
        console.log(`색상: ${PPomi.color}`);
        console.log(`나이: ${PPomi.age}`);
        console.log(`종: ${PPomi.family}`);
        // console.log(`getFamily: ${PPomi.getFamily()}`);


        Dog.prototype.owner = '김사과';
        Dog.prototype.run = function(){
            return this.name + '달립니다!';
        }

        console.log(`Rucy 소유자: ${Rucy.owner}`);
        console.log(`PPomi 소유자: ${PPomi.owner}`);

        console.log(`Rucy run(): ${Rucy.run()}`);
        console.log(`PPomi run(): ${PPomi.run()}`);
    </script>
</body>
</html>



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Math 객체</title>
</head>
<body>
    <script>
        // min(): 가장 작은 수를 반환. 매개변수가 전달되지 않으면 Infinity를 반환
        console.log(Math.min());
        console.log(Math.min(1,10,-10,1000,0,'-100'));
        console.log(Math.min(1,10,-10,'마이너스천',0,'-100'));

        // max(): 가장 큰 수를 반환, 매개변수가 전달되지 않으면 -Infinity를 반환
        console.log(Math.max());
        console.log(Math.max(1,10,-10,1000,0,'-100'));
        console.log(Math.max(1,10,-10,'마이너스천',0,'-100'));

        // round(): 소수점 첫번째 자리에서 반올림하여 그 결과를 반환
        console.log(Math.round(10.49));
        console.log(Math.round(10.5));
        console.log(Math.round(-10.5));
        console.log(Math.round(-10.51));

        // floor(): 소수점을 버림
        console.log(Math.floor(10.49));
        console.log(Math.floor(10.5));
        console.log(Math.floor(-10.5));
        console.log(Math.floor(-10.51));

        // ceil(): 소수점 첫번째 자리에서 소수점을 올림
        console.log(Math.ceil(10.49));
        console.log(Math.ceil(10.5));
        console.log(Math.ceil(-10.5));
        console.log(Math.ceil(-10.51));

        let num = 123.4567;
        console.log(Math.round(num * 100));

        // n번째 자리에서 반올림
        console.log(Math.round(num * 100)/100);
        console.log(num.toFixed(2));

        // random(): 0보다 크거나 같고 1보다 작은 무작위 소수를 반환합ㄴ다.
         const ram= Math.random();
         console.log(ram); // 0.732324



         const number = Math.ceil(Math.random() * 20);
         console.log(number);
    </script>
</body>
</html>

문제
가위, 바위, 보 게임을 만들기
    
    가위, 바위, 보 중 하나를 입력하세요. 가위

    컴퓨터: 바위, 유저: 가위 -> 패

    가위, 바위, 보 중 하나를 입력하세요. 바위

    컴퓨터: 가위, 유저: 바위 -> 승
    프로그램을 종료합니다.

힌트: 파이썬과 같은 방식으로 switch문을 이용해서 경우의 수 패배/비김/승리 각각 3가지로 나뉩니다. 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>가위바위보 게임</title>
</head>
<body>
    <h2>가위바위보 게임</h2>
    <script>
        while(true){
            const com = Math.ceil(Math.random()*3);
            user = prompt('가위바위보 중 하나를 입력하세요: ');
            if(user == '가위'){
                if(com == 1){
                    console.log('컴퓨터: 가위, 유저: 가위, 비겼습니다');
                }else if(com == 2){
                    console.log('컴퓨터: 바위, 유저: 가위, 졌습니다');
                }else {
                    console.log('컴퓨터: 보, 유저: 가위, 이겼습니다');
                    break;
                }
            }else if(user == '바위'){
                if(com == 1){
                    console.log('컴퓨터: 가위, 유저: 바위, 이겼습니다');
                    break;
                }else if(com == 2){
                    console.log('컴퓨터: 바위, 유저: 바위, 비겼습니다');
                }else {
                    console.log('컴퓨터: 보, 유저: 바위, 졌습니다');
                }
            }else{
                if(com == 1){
                    console.log('컴퓨터: 가위, 유저: 보, 졌습니다');
                }else if(com == 2){
                    console.log('컴퓨터: 바위, 유저: 보, 이겼습니다');
                    break;
                }else {
                    console.log('컴퓨터: 보, 유저: 보, 비겼습니다');
                }
            }
        }
        console.log('프로그램을 종료합니다');
    </script>
</body>
</html>



문제2.
로또번호를 추출하는 문서를 만들어보자.
(단, 중복된 숫자를 제거)

힌트: 중복된 숫자는 i--을 이용해 삭제합니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>로또생성기</title>
</head>
<body>
    <h2>로또생성기</h2>
    <script>
        const lotto = [0, 0, 0, 0, 0, 0];
        for(let i=0; i<lotto.length; i++){
            lotto[i] = Math.ceil(Math.random() * 45);
            for(let j=0; j<i; j++){
                if(lotto[i] == lotto[j]){
                    i--;
                }
            }
        }
        console.log(lotto);
    </script>
</body>
</html>
</html>