도움말
인텔리퀀트의 사용방법과 메뉴얼입니다.

7. 객체로 작업하기

JavaScript는 간단한 객체 기반 패러다임을 가진 언어로 설계되었습니다. JavaScript의 객체는 속성 (name-value 쌍)의 모음입니다. 속성 값으로 함수를 이용할 수도 있고, 속성 값으로 사용되는 함수는 그 객체의 메소드입니다. JavaScript 실행 환경에 미리 정의 된 객체를 사용뿐만 아니라 프로그래머 자신이 객체를 정의 할 수 있습니다.

이 장에서는 객체와 속성, 함수 나 메소드 사용법과 프로그래머 자신이 객체를 정의하는 방법을 설명합니다.

Objects overview

다른 많은 프로그래밍 언어에서도 그렇듯, JavaScript의 객체도, 현실 세계의 "사물"(즉 객체)에 비유 할 수 있습니다. JavaScript의 객체의 개념은 현실 세계에 존재하는 "사물"이라는 개념으로 해석 할 수 있습니다.

JavaScript에서 객체는 속성을 가진 독립적인 존재입니다. 컵을 예로 들어 보면, 컵은 다양한 특성(속성)을 가진 사물(객체)입니다. 컵은 색상과 모양, 무게나 재질 등 성질이 있습니다. 마찬가지로, JavaScript의 객체도 속성을 가질 수 있고, 속성은 그 객체의 특징을 나타낼 수 있습니다.

객체 및 속성

JavaScript의 객체는 자신과 관련된 속성이 있습니다. 객체의 속성은 객체에 연결된 변수 파악할 수 있습니다. 객체의 속성은 기본적으로 객체에 속해 있다는 점을 제외하고 일반 JavaScript 변수와 같은 것입니다. 객체의 속성은 객체의 특성을 정의합니다. 다음과 같이 객체 이름과 속성을 단순히 점(.) 뒤에 이름을 적어 객체의 속성에 액세스 할 수 있습니다.

objectName.propertyName

모든 JavaScript의 변수와 같이 객체 이름과 속성 이름은 대/소문자를 구분합니다. 속성에 값을 할당하여 속성을 정의 할 수 있습니다. 다음과 같이하여 myCar라는 객체를 만들고 반면 make, model, year라는 속성을 부여 할 수 있습니다

var myCar = new Object();
myCar.make = "Ford";
myCar.model = "Mustang";
myCar.year = 1969;

또한 자바스크립트 객체의 속성은 대괄호 기호를 사용하여 접근하거나 저장할 수 있습니다. 객체는 다른말로 연관 배열이라고 부릅니다. 각 속성은 연관된 스트링 값을 통하여 접근할 수 있기 때문입니다. 예를 들어 myCar 객체의 속성은 아래처럼 접근할 수 있습니다.

myCar["make"] = "Ford";
myCar["model"] = "Mustang";
myCar["year"] = 1969;

객체의 속성 이름은 유효한 스트링 값(빈 스트링을 포함하여) 또는 스트링으로 변환할 수 있는 것이어야 합니다. 유효하지 않은 자바스크립트 식별자(예를 들어 속성이름은 공백이나 대시(-) 또는 숫자로 시작하는 문자)는 대괄호 기호를 사용할 수 있습니다. 이 기호는 속성 이름을 동적으로 정의할 때 매우 유용합니다. (속성 이름이 런타임 이전에는 결정되지 않은 경우). 예제는 아래입니다:

var myObj = new Object(),
str = "myString",
rand = Math.random(),
obj = new Object();
 
myObj.type              = "Dot syntax";
myObj["date created"]   = "String with space";
myObj[str]              = "String value";
myObj[rand]             = "Random Number";
myObj[obj]              = "Object";
myObj[""]               = "Even an empty string";
 
console.log(myObj);

또한 속성은 저장된 스트링 변수를 이용하여 접근할 수 있습니다.

var propertyName = "make";
myCar[propertyName] = "Ford";

propertyName = "model";
myCar[propertyName] = "Mustang";

대괄호 기호는 for-in 구문에서 객체의 모든 속성을 열거하기 위해 사용할 수 있습니다. 이 동작을 설명하기 위해, 아래 showProps() 함수는 전달된 객체의 모든 석성을 보여줍니다.

function showProps(obj, objName) {
  var result = "";
  for (var i in obj) {
    if (obj.hasOwnProperty(i)) {
        result += objName + "." + i + " = " + obj[i] + "\n";
    }
  }
  return result;
}

이제 showProps(myCar, "MyCar") 를 호출하면 아래처럼 리턴됩니다.

myCar.make = Ford
myCar.model = Mustang
myCar.year = 1969

모든것은 객체

자바스크립트에서 모든 것은 객체입니다. null과 undefined를 제외한 모든 primitive타입은 객체로 처리합니다. 이들은 속성을 가지고 있습니다. (어떤 타입의 주어진 속성은 영구적이지 않습니다.)

객체의 모든 속성 열거하기.

ECMAScript5 규약에서 객체의 속성을 접근하는 방법은 3가지 입니다.

1. for-in 반복문
이방법은 객체의 모든 열거 가능한 속성과 프로토타입 체인을 순회할 수 있습니다.

2. Object.keys(o)
이 방법은 객체가 가지고 있는 열거 가능한 속성 이름들을 배열로 반환합니다. (프로토타입 체인은 포함하지 않습니다.)

3. Object.getOwnPropertyNames(o)
이 메소드는 열거 가능여부에 관계없이 모든 속성의 이름을 배열로 반환합니다.
ECMAScript5에서는 모든 객체의 속성 목록을 가져올 수 있는 직접적인 방법은 없습니다. 그러나 아래처럼 접근할 수는 있습니다.

function listAllProperties(o){     
    var objectToInspect;     
    var result = [];
     
    for(objectToInspect = o; objectToInspect !== null; objectToInspect = Object.getPrototypeOf(objectToInspect)){  
        result = result.concat(Object.getOwnPropertyNames(objectToInspect));  
    }
     
    return result; 
}

이것은 숨겨진 속성을 찾아내는 유용한 방법입니다. (동일한 이름을 가진 또다른 속성이 이미 프로토타입 체인에 존재한다면. 프로토타입 체인 내부의 속성은 객체를 통해 접근 할 수 없습니다. ) 접근 가능한 속성 리스트는 배열의 중복제거로 쉽게 수행할 수 있습니다.

새로운 객체 생성

자바스크립트는 몇개의 미리 정의된 객체들을 가지고 있습니다. 뿐만 아니라 당신은 새로운 객체를 작성할 수 있습니다. 자바스크립트 1.2 이후부터 객체 initializer를 사용하여 객체를 생성할 수 있습니다. 추가적으로 당신은 생성자 함수를 만들고, 이것을 new 연산자를 사용하여 인스턴스를 만들 수도 있습니다.

객체 initializer 사용

생성자 함수를 사용하여 객체를 생성하는 방법 이외에도 객체 initializer를 사용하여 객체를 만들 수 있습니다. 객체 initializer는 리터럴 기호를 사용하여 객체를 생성합니다. "객체 initializer" 는 C++에서 사용하는 용어와 동일합니다.

다음 구문은 객체 initializer를 사용하는 방법입니다.

var obj = { property_1:   value_1,   // property_# may be an identifier...
            2:            value_2,   // or a number...
            // ...,
            "property n": value_n }; // or a string

여기서 obj는 새 오브젝트이 이름이고, 각 property_i는 식별자입니다.(이름, 숫자, 또는 문자열 리터럴이 가능), 그리고 각 value_i는 property_i 의 값을 지정하는 표현식입니다. 변수에 대입 하는것이 필수는 아닙니다. 만약 이 객체를 아무데서도 접근할 필요가 없다면 여기서처럼 obj 변수로 지정할 필요는 없습니다. 중요한 것은 중괄호로 감싼다는 점입니다.

만약 initializer로 생성하는 객체가 스크립트 최상위에서 있다면 자바스크립트는 스크립트가 해석될때 객체를 생성합니다. 또한 initializer가 함수내부에 있다면 그 함수가 호출 될때 객체를 생성합니다.

다음 구문은 cond가 true일 경우에만 객체를 생성하고 x라는 변수에 지정하는것을 보여 줍니다.

if (cond) var x = {hi: "there"};

다음 예제는 myHonda를 3개의 속성과 함께 생성합니다. 그중 engine 속성은 자체적인 2개의 속성을 가진객체라는 점을 눈여겨 보세요.

var myHonda = {color: "red", wheels: 4, engine: {cylinders: 4, size: 2.2}};

또한 객체 initializer를 배열을 생성하는데 이용할 수 있습니다. 자세한 내용은 배열 리터럴 항목을 보세요.

In JavaScript 1.1 and earlier, you cannot use object initializers. You can create objects only using their constructor functions or using a function supplied by some other object for that purpose. See Using a constructor function.

자바스크립트 1.1 이전에서는 객체 initializer를 사용할 수 없습니다. 생성자 함수 또는 객체 생성을 위한 함수를 통해서만 가능합니다. 자세한 내용은 생성자 함수 항목을 보세요.

생성자 함수

반면, 다음 두 스텝으로 객체를 생성할 수 있습니다.
1. 생성자 함수를 이용하여 객체 타입을 만듭니다. 이때 대문자로 시작하는 것을 강력히 추천합니다.
2. 이 객체의 인스턴스를 new 연산자를 이용하여 만듭니다.

객체 타입을 정의하기 위해 이름, 속성, 메소드를 정의한 함수를 작성해야 합니다. 예를 들어 car라고 불리고 make, model, year라는 속성을 가진 자동차 객체 타입을 생성한다면 아래처럼 함수를 작성해야 합니다.

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}

중요한것은 객체의 프로퍼티가 함수의 인자로 전달되는 점입니다.

이제 mycar라는 객체를 아래처럼 생성할 수 있습니다.

var mycar = new Car("Eagle", "Talon TSi", 1993);

이 구문은 mycar를 만들고 각각의 속성을 지정합니다. 이제 mycar.make는 "Eagle" 값이고, mycar.year는 1993이 됩니다.

car객체는 아래 예제처럼 여러개를 생성할 수 있습니다.

var kenscar = new Car("Nissan", "300ZX", 1992);
var vpgscar = new Car("Mazda", "Miata", 1990);

객체는 속성을 가질 수 있고, 이 속성은 다른 객체일 수 있습니다. 예를 들어 person이라는 객체가 아래처럼 정의되어 있다면

function Person(name, age, sex) {
  this.name = name;
  this.age = age;
  this.sex = sex;
}

두 개의 새로운 person객체를 생성할 수 있습니다.

var rand = new Person("Rand McKinnon", 33, "M");
var ken = new Person("Ken Jones", 39, "M");

Then, you can rewrite the definition of car to include an owner property that takes a person object, as follows:
그리고 car클래스에 person객체인 owner라는 속성을 추가할 수 있습니다.

function Car(make, model, year, owner) {
  this.make = make;
  this.model = model;
  this.year = year;
  this.owner = owner;
}

새로운 객체를 만들기 위해 아래처럼 사용합니다.

var car1 = new Car("Eagle", "Talon TSi", 1993, rand);
var car2 = new Car("Nissan", "300ZX", 1992, ken);

요점은 새로운 객체를 생성할때 리터럴 문자열이나 숫자가 아닌 위에서 성성된 rand와 ken이 owner의속성으로 전달되었다는 점입니다. 만약 car2의 owner 이름이 필요할때 아래처럼 접근할 수 있습니다.

car2.owner.name

미리 정의된 객체에 속성을 추가할 수도 있습니다.

car1.color = "black";

위에서는 car1에 color이라는 속성을 추가하고 값을 "black"으로 지정 하였습니다. 이때 다른 car 객체들에는 영향을 미치지 않습니다. 같은 타입의 모든 객체에 속성을 추가하기 위해서는 car 객체에 속성을 정의해야 합니다.

Object.create 메소드 사용

객체는 Object.create 메소드를 이용하여 만들수도 있습니다. 이 메소드는 메우 유용하게 사용할 수 있습니다. 만들고자 하는 객체를 생성자 함수를 정의하지 방법이 아닌 기존에 존재하는 객체의 prototype을 선택하여 생성하기 때문입니다. 더 자세한 내용은 Object.create항목을 참고하세요.

상속

자바스크립트상의 모든 객체는 적어도 하나 이상의 객체로 부터 상속 받습니다. 객체는 prototype으로 알려진 것에서 상속 받은 것입니다. 그리고 상속받은 속성들은 생성자의 prototype객체를 통해 접근할 수 있습니다.

객체 속성 인덱싱

자바스크립트 1.0에서는, 자바스크립트의 속성을 접근하기 위해 인덱스를 사용해야 했습니다. 자바스크립트 1.1 부터는 속성을 이름으로 초기화 하였다면 이름을 사용해야 합니다. 만약 인덱스를 통해 초기화 하였다면 이름을 사용하여야 합니다.

이 제한은 객체와 그 속성을 생성자 함수를 통해 생성하고 각 속성을 명시적으로 선언할때 적용됩니다. (예를 들어, 위 Car객체에서 myCar.color = "red") 만약 인덱스를 통해 객체를 생성하였다면 (ex. myCar[5] = "25 mpg) 이 속성을 인덱스로 접근해야만 합니다. (ex. var foo = myCar[5];)

다만 HTML에서 form 배열같은 객체를 접근할 경우에는 예외입니다. 이런 경우에는 일반적인 숫자로 배열에 접근할 수 있습니다. 예를 들어 HTML 문서의 두번째

태그의 NAME 어트리뷰트가 "myForm" 이라면, document.forms[1] 또는 document.forms["myForm"] 모두 가능합니다.

객체 타입의 속성 정의

앞에서 정의한 객체 타입은 prototype 속성을 이용하여 정의할 수 있습니다. 이 property 속성은 특정 타입의 모든 객체에서 공유됩니다. 다음 코드는 car 타입의 모든 객체에 color 속성을 추가하고 car1 객체의 color 속성을 지정하는 예제입니다.

Car.prototype.color = null;
car1.color = "black";

함수객체의 prototype 속성에 관한 더 많은 자료는 자바스크립트 레퍼런스를 참고하세요.

메소드 정의

메소드는 객체와 함께 동작하는 함수(function)입니다. 더 간단하게는 객체의 함수(function) 속성입니다. 메소드는 일반적으로 function으로 정의됩니다. 드물게 객체의 속성으로 정의되기도 합니다. 예를 들어

objectName.methodname = function_name;
 
var myObj = {
  myMethod: function(params) {
    // ...do something
  }
};

여기서 objectName은 기존에 존재하는 객체입니다. methodname은 메소드로 정의된 이름입니다. 그리고 function_name은 말 그대로 함수의 이름입니다.

이 메소드는 객체의 컨텍스트에서 다음과 같이 호출됩니다.

object.methodname(params);

You can define methods for an object type by including a method definition in the object constructor function. For example, you could define a function that would format and display the properties of the previously-defined car objects; for example,
객체의 메소드는 그 객체의 생성자 함수 내에서 메소드 정의할 수 있습니다. 예를 들어, 앞에서 정의한 car 객체에서 속성들을 format & display 하는 함수는 아래처럼 정의할 수 있습니다.

function displayCar() {
  var result = "A Beautiful " + this.year + " " + this.make + " " + this.model;
  pretty_print(result);
}

여기서 pretty_print는 한줄로 출력하는 함수 입니다. 객체의 메소드에서 자신의 속성들에 접근하는 방법을 눈 여겨 보세요.

이 함수는 car에 메소드를 추가하여 동일하게 만들 수 있습니다.

this.displayCar = displayCar;

객체 정의해서 car 타입의 전체 정의는 아래와 같습니다.

function Car(make, model, year, owner) {
  this.make = make;
  this.model = model;
  this.year = year;
  this.owner = owner;
  this.displayCar = displayCar;
}

이제 displayCar 메소드를 모든 객체에서 사용할 수 있습니다.

car1.displayCar();
car2.displayCar();

객체 참조 사용

자바스크립트는 메소드 내에서 현재 객체를 참조할 수 있는 특별한 키워드를 가지고 있습니다. 예를 들어, 객체의 값 속성이 주어진 범위에서 정상적인지를 확인하기 위해 validate() 함수를 호출한다면 다음과 같이 할 수 있습니다.

function validate(obj, lowval, hival) {
  if ((obj.value < lowval) || (obj.value > hival))
    alert("Invalid Value!");
}

각 form 엘리먼트에서 onchange이벤트가 발생한다면, validate 함수를 다음처럼 엘리먼트를 인자로 전달 할 수 있습니다.

< input type="text" name="age" size="3"
  onChange="validate(this, 18, 99)">

일반적으로, 메소드 내에서 객체의 함수를 호출하기 위해 이 방법을 사용합니다.

form의 속성이 여러개라면, 현재 객체의 부모 form을 참고할 수 있습니다. 다음 예제를 보면, myForm이라는 폼은 텍스트 객체와 버튼을 가지고 있습니다. 사용자가 버튼을 누르면, 텍스트 객체의 값을 form의 이름으로 설정합니다. 버튼의 onclick 이벤트 핸들러에서 this.form 을 사용하여 부모 폼인 myForm을 참조할 수 있습니다.


< label >Form name:< input type="text" name="text1" value="Beluga">

< input name="button1" type="button" value="Show Form Name" onclick="this.form.text1.value = this.form.name">

getter와 setter 정의

getter는 특정 속성의 값을 가져오는 메소드 입니다. setter는 특정 속성의 값을 지정하는 메소드 입니다. 미리 정의된 자바스크립트 코어 객체 뿐만 아니라 사용자가 정의한 어떤 객체라도 추가된 새로운 속성을 지원하기 위해 getter와 setter를 정의할 수 있습니다. getter와 setter는 객체 리터럴 문법을 사용합니다.

JavaScript 1.8.1 이상 참고.
자바스크립트 1.8.1 부터 객체의 속성을 입력하고 배열을 초기화 할 때 setter가 호출되지 않습니다.

다음 JS 쉘은 getter와 setter가 사용자 정의 객체 o 에서 어떻게 동작하는지 보여줍니다. JS쉘이란 배치모드 또는 인터렉티브하게 자바스크립트를 테스트 하기 위한 코멘드 라인 기반의 어플리케이션입니다.

js> var o = {a: 7, get b() {return this.a + 1;}, set c(x) {this.a = x / 2}};
[object Object]
js> o.a;
7
js> o.b;
8
js> o.c = 50;
js> o.a;
25


o 객체의 속성은
o.a — 숫자
o.b — o.a에 1을 더해서 리턴하는 getter
o.c — 값을 2로 나누어 o.a에 저장하는 setter

Please note that function names of getters and setters defined in an object literal using "[gs]et property()" (as opposed to __define[GS]etter__ below) are not the names of the getters themselves, even though the [gs]et propertyName(){ } syntax may mislead you to think otherwise. To name a function in a getter or setter using the "[gs]et property()" syntax, define an explicitly named function programmatically using Object.defineProperty (or the Object.prototype.__defineGetter__ legacy fallback).

자바스크립트 쉘을 통해 getter와 setter가 Date라는 미리 정의된 객체의 모든 인스턴스에 year 속성을 추가하여 Date의 prototype을 확장하는것을 보여드리겠습니다. Date클래스에 존재하는 getFullYear와 setFullYear 메소드는 year 속성의 getter와 setter를 작성하는데 사용합니다.

다음 구문은 year 속성의 getter와 setter를 정의합니다.

js> var d = Date.prototype;
js> d.__defineGetter__("year", function() { return this.getFullYear(); });
js> d.__defineSetter__("year", function(y) { this.setFullYear(y); });

These statements use the getter and setter in a Date object: 다음에 Date 객체에서 getter와 setter를 사용합니다.

js> var now = new Date;
js> print(now.year);
2000
js> now.year = 2001;
987617605170
js> print(now);
Wed Apr 18 11:13:25 GMT-0700 (Pacific Daylight Time) 2001

구버전 문법들

과거에는 자바스크립트가 getter와 setter를 정의할 수 있는 여러 문법을 지원하였습니다. 이제 대부분의 스크립트 엔진에서 제공하지 않습니다. 더 이상 사용하지 않는 문법들에 대한 자세한 내용은 "삭제된 문법" 항목을 참고하세요.

요약

일반적으로 getter와 setter는 다음 두 가지 방법 모두 가능합니다.

- 객체 initializer를 사용
- 객체를 생성한 이후에 언제라도 getter와 setter 메소드를 추가

객체 initializer를 사용하여 getter와 setter를 정의할 때, getter 메소드 get 선언과 setter 메소드 set 선언이 필요한 전부입니다. 당연히 getter 메소드는 파라메터를 사용할 수 없고, setter 메소드는 하나의 파라메터를 사용합니다.

var o = {
  a: 7,
  get b() { return this.a + 1; },
  set c(x) { this.a = x / 2; }
};

getter와 setter는 객체가 생성된 이후 언제라도 __defineGetter__ 와 __defineSetter__. 두 개의 특별한 메소드를 통해 추가할 수 있습니다. 두 메소드의 첫 번째 인자는 스트링으로 된 getter 또는 setter의 이름이며, 두번째 인자는 그 함수입니다.

o.__defineGetter__("b", function() { return this.a + 1; });
o.__defineSetter__("c", function(x) { this.a = x / 2; });

이 두 가지 스타일은 손에 익은 프로그래밍 스타일에 따라 선택하면 됩니다. 만약 프로토타입을 정의할 때 객체 initializer를 사용하였다면 아마도 첫 번째 스타일을 사용할 것입니다. 이 방법은 던 간결하고 자연스럽습니다. 그러나 나중에 객체에 getter 와 setter를 정의할 필요가 있다면 (프로토타입을 직접 작성한게 아니거나 부분객체라면) 두 번째 방법만이 사용 가능합니다. 두번째 방법은 자바스크립트의 세계에서는 자연스러운 표현이지만, 읽기도 이해하기 어렵습니다.

속성 제거

delete 연산자를 사용하여 객체의 속성을 제거 할 수 있습니다. 다음은 속성을 제거하는 예제를 보여줍니다.

//a, b 두 개의 속성을 가진 새로운 객체 myobj를 생성합니다.
var myobj = new Object;
myobj.a = 5;
myobj.b = 12;
 
//a 속성을 삭제하여 b속성만 남게 됩니다.
delete myobj.a;

var 키워드를 사용하지 않고 변수를 선언했다면, delete 구문을 사용하여 글로벌 변수도 삭제할 수 있습니다.

g = 17;

delete g;

저작권 공지

이 문서의 모든 저작권은 Mozilla.org에 있습니다. 이 문서는 "모질라 기여자"들에 의해 작성 되었습니다. 원문 보기
저희가 한글로 번역한 2차적저작물에 대한 저작권 역시 Mozilla.org에 있습니다.