2013년 2월 20일 수요일

[JS] 객체


자바스크립트는 객체지향 언어!

객체모형(Object Model)
브라우저 객체 : Window, Document, Location 등 (DOM)
내장 객체 : Date, Math, Array 등

특징
클래스 선언과 상속을 지원하지 않지만 객체의 정의가 가능하다. 그러나 한정된 수준에 그친다. 객체의 생성과 상속이 다른 언어처럼 완벽하지는 않으나 어느정도의 형태는 비슷하게 취할 수 있다.

객체의 생성
예)
var product{
    제품명 : "7D 건조 망고',
    유형 : "당절임",
    성분 : "망고, 설탕",
    원산지 : "필리핀"
}
이처럼 객체를 정의할 때 사용하는 방법이 Json표기법이다. 키값인 제품명, 유형 등으로 값(Value)를 뽑아 오는 방법이다. (Hash자료구조를 떠올리면 비슷하다.)

속성접근
product.제품명
product.유형

생성자 함수
객체를 만드는 방법은 여러가지가 있지만 개인적으로는 생성자 함수로 객체를 생성하는 것이 코드의 재사용측면에서 좋고 자바에서의 생성자 함수와 유사하게 사용하기 때문에 좀 더 쉽게 와닿는다.

예)
function Student(name, kor, eng, mat){
    this.name = name;
    this.kor = kor;
    this.eng = eng;
    this.mat = mat;

////생성자에서 매서드 추가//////
    this.getSum = function(){
        return this.kor + this.eng + this.mat;
    }
    this.getAvg = function(){
        return this.getSum()/3;
    }
}

프로토타입
위와 같이 student객체를 new키워드로 만들 수 있다. 그러나 문제가 있다. 매번 객체를 생성할 때마다 생성자 안에 선언한 함수를 계속해서 개체의 속성으로 만드는 것이다. 분명 메모리 낭비이다.

이를 해결하기 위해 프로토타입이 생겼다. 객체의 매서드부분만 따로 모아서 공유하는 것을 말한다.
예)

function Student(name, kor, eng, mat){
    this.name = name;
    this.kor = kor;
    this.eng = eng;
    this.mat = mat;
}//생성자 정의 끝

Student.prototype.getSum = function(){
    return this.kor + this.eng + this.mat;
}
Student.prototype.getAvg = function(){
    return this.getSum()/3;
}

이렇게함으로써 자바에서 만들던 객체의 틀인 클래스와 비슷?하게되었다. 그러나 절대 클래스가 아니라는 것을 꼭 기억하자. 자바스크립트에는 클래스라는 개념이 없다. 하지만 실재로는 다음과 같은 방식으로 많이 사용한다.

예)

function Student(name, kor, eng, mat){
    this.name = name;
    this.kor = kor;
    this.eng = eng;
    this.mat = mat;
}//생성자 정의 끝


Student.prototype = {
    getSum : function(){

        return this.kor + this.eng + this.mat;
    },
    getAvg : function(){

        return this.getSum()/3;
    }
}

이렇게 프로토타입으로 매서드를 묶어서 이용한다. 사용법은 둘다 같다.
이렇듯 객체는 하나의 프로토타입 객체를 가지고 있고 그 목적은 객체의 메서드들을 관리하기 위한 용도이다.

캡슐화
만일의 상황을 대비하여 특정 속성이나 매서드를 사용자가 알 수 없도록 또는 알 필요가 없도록 숨겨놓은 것이다. 즉 개발자의 의도가 잘 반영되어 사용자가 코드를 재사용하는데 혼돈하지 않거나 의도되지 않은 행위를 막을 수 있는 등 다양한 이점이 있다.

상속
기존의 생성자 함수나 객체를 기반으로 새로운 생성자 함수나 객체를 만드는 것
예)
function Unit(name) {
this.name = name;

this.attack = function(unit) {
alert(this.type + "유닛인 " + this.name + "이 " + unit.type + "유닛인 "
+ unit.name + " 공격!");
unit.attacked(this);
}
this.attacked = function(unit) {
alert(this.type + "유닛인 " + this.name + "이 " + unit.type + "유닛인 "
+ unit.name + "으로부터 공격받음!");
}
}

function BionicUnit(type, name) {
this.type = type;
this.base = Unit;
this.base(name);
}

function MechanicUnit(type, name) {
this.type = type;
this.base = Unit;
this.base(name);
}

window.onload = function() {
BionicUnit.prototype = new Unit;
MechanicUnit.prototype = new Unit;

var unit1 = new BionicUnit("지상", "마린");
var unit2 = new MechanicUnit("공중", "커세어");

unit1.attack(unit2);
alert(unit1 instanceof Unit);
}

상속을 아주 잘 보여주는 예이다. 먼저 부모가 되는 유닛을 정의했다. 생성자 함수안에 이름 속성과 2개의 매서드를 정의했다.

그다음 바이오닉유닛과 메카닉유닛을 정의하였고 윈도우에 이벤트를 걸어 실행해보았다. 상속에서 가장 핵심인부분이 진한 글씨로 표현한 곳이다. 유닛을 base라는 속성으로 받아와 유닛의 이름을 초기화하였고 유닛의 매서드들을 각각의 객체에 프로토타입에 추가함으로써 상속이 이루어지는 것이다.

마지막에 alert창을 띄워 상속이 잘 되었는지 instanceof키워드로 확인해보고 있다.

상속의 예를 하나 더 들어보자. 이번엔 call()함수를 이용한 상속이다.

function Rectangle(w, h){
this.width = w;
this.height = h;

this.getWidth = function(){ return this.width;};
this.getHeight = function(){ return this.height;};
this.setWidth = function(value){
if(value < 0){
throw "길이는 음수일 수 없습니다.";
} else{
this.width = value;
}
}
this.setHeight = function(value){
if(value < 0){
throw "높이는 음수일 수 없습니다.";
} else{
this.height = value;
}
}
}
Rectangle.prototype.getArea = function(){
return this.getWidth()*this.getHeight();
}


function Square(length){
Rectangle.call(this, length, length);
}
Square.prototype = new Rectangle();
Square.prototype.constructor = Square;

var square = new Square(5);
var rectangle = new Rectangle(5, 7);

alert(rectangle.getArea() + " " + square.getArea());

Square생성자에서 Rectangle를 생성하는데 call()를 이용해서 this를 인자로 넘겨주고 있다. 이렇게 함으로써 Rectangle객체의 this는 Square을 가르키게 되고 따라서 상속이 되었다고 할 수 있다. 즉, this를 원하는 객체로 재정의 하는 것이다. call()함수는 자주 쓰일 함수이므로 그 쓰임을 잘 이해하자

댓글 없음:

댓글 쓰기