[JavaScript]オブジェクト


オブジェクト

객체 선언
    <p>
        중괄호{}를 사용해서 객체를 생성하고 속성에는 모든 자료형이 올 수 있다. <br>
        객체는 속성명을 사용해서 속성을 식별한다. <br>
        속성명에 공백이나 특수문자 등이 포함된 경우 따옴표로 묶어서 표기해야 한다. <br>
        또한 객체에서 접근 시 무조건 대괄호를 사용해야 객체의 속성에 접근이 가능하다.
    </p>

    <button id="btn1">실행 확인</button>

    <div id="area1" class="area"></div>
    
    // 객체 선언
    let btn1 = document.getElementById('btn1');

    btn1.addEventListener('click', () => {
        let area = document.getElementById('area1');
        let product = {
            // 'pName' : '아이폰 6s',
            '0' : '배열 흉내',
            pName : '아이폰 6s',
            price : 70000,
            brand : '삼성',
            brand : '애플', // 중복 선언하게 되면 마지막에 선언된 속성이 덮어쓰게 된다.
            spec : ['LED', 'IOS14', '64GB']
            
        };

        console.log(product);

        area.innerHTML = `객체 선언 테스트<br>`;
        area.innerHTML += `객체명['속성명']으로 접근하는 방법<br>`;
        // area.innerHTML += `product['0'] : ${product['0']}<br>`;
        area.innerHTML += `product[0] : ${product[0]}<br>`;
        // area.innerHTML += `product[pName] : ${product[pName]}<br>`; 숫자형태 문자가 아닌 일반적인 문자형태의 속성명은 따옴표로 감싸줘야한다.
        area.innerHTML += `product['pName'] : ${product['pName']}<br>`;
        area.innerHTML += `product['price'] : ${product['price']}<br>`;
        area.innerHTML += `product['brand'] : ${product['brand']}<br>`;
        area.innerHTML += `product['spec'] : ${product['spec']}<br>`;
        area.innerHTML += `product['spec'][0] : ${product['spec'][0]}<br>`;
        area.innerHTML += `product['spec'][1] : ${product['spec'][1]}<br>`;
        area.innerHTML += `product['spec'][2] : ${product['spec'][2]}<br><br>`;

        area.innerHTML += `객체명.속성명으로 접근하는 방법<br>`;
        // area.innerHTML += `product.0 : ${product.0}<br>`; 숫자형태 문자는 대괄호 접근만 가능
        area.innerHTML += `product.pName : ${product.pName}<br>`;
        area.innerHTML += `product.price : ${product.price}<br>`;
        area.innerHTML += `product.brand : ${product.brand}<br>`;
        area.innerHTML += `product.spec : ${product.spec}<br>`;
        area.innerHTML += `product.spec[0] : ${product.spec[0]}<br>`;
        area.innerHTML += `product.spec[1] : ${product.spec[1]}<br>`;
        area.innerHTML += `product.spec[2] : ${product.spec[2]}<br><br>`;

        let user = {
            'user name' : '이종훈',
            user_age : 30,
            'id!!' : 'aljongjong'  
        };

        area.innerHTML += `공백이나 특수문자가 속성명에 있는 경우 대괄호를 이용해서 값을 가져올 수 있다.<br>`;
        // area.innerHTML += `user.user name : ${user.'user name'} <br>`;
        area.innerHTML += `user['user name'] : ${user['user name']} <br>`;
        area.innerHTML += `user.user_age : ${user.user_age} <br>`;
        // area.innerHTML += `user.id!! : ${user.id!!} <br>`;
        // area.innerHTML += `user.'id!!' : ${user.'id!!'} <br>`;
        area.innerHTML += `user['id!!'] : ${user['id!!']} <br>`;


객체의 메소드
    <p>
        객체의 속성 중 함수 자료형인 속성을 메소드라고 한다. 
    </p>

    <button id="btn2">실행 확인</button>
    
    // 객체의 메소드
    let btn2 = document.getElementById('btn2');
        
    btn2.addEventListener('click', () => {
        let dog = {
            name : '아인',
            kind : '웰시 코기',
            eat : function(food) {
                // this를 명시적으로 꼭 써줘야한다.(객체 내부의 속성에 접근하기 위해서는 'this.속성명'으로 작성한다.)
                console.log(`${this.kind} 종류인 ${this.name}이 ${food}를 먹습니다.`);
            }
        };

        dog.eat('당근');
    });
객체와 반복문
    <p>
        객체가 가지고 있는 모든 속성들에 순차적으로 접근하려면 <br>
        단순 for 문으로 불가능하다. 따라서 for in 문을 사용해야 한다.
    </p>

    <button id="btn3">실행 확인</button>
    
    // 객체와 반복문
    let btn3 = document.getElementById('btn3');

    btn3.addEventListener('click', () => {
        let game = {
            title : '마비노기',
            price : '₩9,900/M',
            supportOS : ['window', 'MacOS'],
            service : true
        };

        console.log(game);

        for (const key in game) {
            console.log(`key : ${key}, game[key] : ${game[key]}`);
        }
    });
객체의 속성 추가 및 제거
    <p>
        객체를 생성한 이후에 새로운 속성을 추가하거나 제거할 수 있다. (동적으로 속성을 추가/제거)
    </p>

    <button id="btn4">실행 확인</button>
    
    // 객체의 속성 추가 및 제거
    let btn4 = document.getElementById('btn4');

    btn4.addEventListener('click', () => {
        let student = {};

        // 객체의 속성 추가
        student.name = '홍길동';
        student.age = 30;
        student['job'] = '의사';

        // 객체에 메소드 추가
        student.whoAreYou = function() {
            let str = '';
            for (const key in this) {
                if(typeof(this[key]) != 'function') {
                    str += `${key} : ${this[key]} `;

                }
            }

                return str;
        };

        console.log(student);
        console.log(student.whoAreYou());
        console.log('job' in student);
        console.log('height' in student);

        delete(student.job);

        console.log(student);
        console.log(student.whoAreYou());
        console.log('job' in student);
    });
객체 배열
    <p>
        객체와 배열을 사용해서 데이터를 관리할 수 있다.
    </p>
    
    <button id="btn5">실행 확인</button>
    
    // 객체 배열
    let btn5 = document.getElementById('btn5');

    btn5.addEventListener('click', () => {

        // 배열을 사용하지 않을 경우
        let student1 = {name : '이종훈', java : 100, oracle : 70};
        let student2 = {name : '홍길동', java : 70, oracle : 10};
        let student3 = {name : '백구', java : 100, oracle : 100};
        let student4 = {name : '누렁이', java : 90, oracle : 90};
        let student5 = {name : '이몽룡', java : 20, oracle : 20};

        console.log(student1);
        console.log(student2);
        console.log(student3);
        console.log(student4);
        console.log(student5);

        // 배열 선언 및 초기화
        let students = [
            {name : '이종훈', java : 100, oracle : 70},
            {name : '홍길동', java : 70, oracle : 10}
        ]

        // 배열에 요소 추가
        students.push({name : '백구', java : 100, oracle : 100});
        students.push(student4);
        students.push(student5);

        // 배열에 담겨있는 모든 객체에 메소드를 추가
        for (let i = 0; i < students.length; i++) {
            students[i].getSum = function() {
                return this.java + this.oracle
            };

            students[i].getAvg = function() {
                return this.getSum() / 2;
            };
        }

        console.log(students);

        // 모든 학생의 정보가 담긴 배열을 출력
        for (const index in students) {
            with(students[index]) {
                console.log(`이름 : ${name}, 총점 : ${getSum()}, 평균 : ${getAvg()}`);
            }
        }
    });
생성자 함수
    <p>
        new 키워드를 사용해 객체를 생성할 수 있는 함수를 의미한다.
    </p>

    <button id="btn6">실행 확인</button>
    
    // 생성자 함수
    function Student(name, java, oracle) {
        // 속성 정의
        this.name = name;
        this.java = java;
        this.oracle = oracle;

        // 메소드 정의
        // this.getSum =function() {
        //     return this.java + this.oracle;
        // }
        // this.getAvg =function() {
        //     return this.getSum() / 2;
        // }
    }

    // 객체마다 getSum, getAvg 함수를 가지고 있는게 아니고 연결된 prototype에 있는 getSum, getAvg 함수를 참조하게 만든다. toString.. 등의 함수는 최상위 Object클래스의 prototype을 참조하는 것이다. -> 프로토타입의 객체 지향 언어
    Student.prototype.getSum = function() {
        return this.java + this.oracle;
    };
    Student.prototype.getAvg = function() {
        return this.getSum() / 2;
    };

    let btn6 = document.getElementById('btn6');

    btn6.addEventListener('click', () => {
        let student = new Student('박효신', 80, 90);
        let students =[];

        students.push(student);
        students.push(new Student('이솜', 70, 60));
        students.push(new Student('질렌할', 40, 50));

        // 생성자 함수로 만들어진 객체의 경우 해당 객체가 어떤 생성자 함수로 생성되었는지 instanceof 연산자로 검사할 수 있다.
        console.log(student instanceof Student);
        console.log(student);

        console.log(students instanceof Student);
        console.log(students);

        // 모든 학생의 정보가 담긴 배열을 출력(이름, 총점, 평균)
        for (const index in students) {
            console.log(`이름 : ${students[index].name}, 총점 : ${students[index].getSum()}, 평균 : ${students[index].getAvg()}`);
        }
    });
캡슐화
    <p>
        생성자 함수에 속성을 정의할 때 this. 키워드를 사용하지 않고 지역변수로 선언할 경우<br>
        캡슐화된 객체의 속성은 직접 접근할 수 없으므로 간접적으로 접근할 수 있도록 getter/setter 메소드를 정의해야 한다.
    </p>

    <button id="btn7">실행 확인</button>
    
    // 캡슐화
    function IdolGroup(n, m) {
        let name = n;
        let member = m; // 지역 변수 외부에서 접근 불가

        this.getGroupName = function() {
            return name;
        }
        this.getMembers = function() {
            return member;
        }
        this.getMemberCount = function() {
            return member.length;
        }

        this.setGroupName = function(n) {
            name = n;
        }
        this.setMembers = function(m) {
            member = m;
        }
    }

    let btn7 = document.getElementById('btn7');

    btn7.addEventListener('click', () => {
        // 생성자 함수를 이용하여 객체를 생성
        let idol = new IdolGroup('에스파', ['윈터','닝닝','지젤','카리나']);

        console.log(idol);
        console.log(idol.getGroupName(), idol.getMembers(), idol.getMemberCount());

        idol.setGroupName('참프루');
        idol.setMembers(['진','무겐','후우']);

        console.log(`그룹명 : ${idol.getGroupName()}, 멤버 : ${idol.getMembers()}, 멤버수 : ${idol.getMemberCount()}`);
    });