반응형

 자바스크립트의 객체는 이름:값 형태의 속성들을 저장하는 컨테이너이다. 값은 객체(함수, 배열, 정규식 포함) 또는 기본 데이터 타입이 될 수 있다. 함수를 값으로 하는 속성을 메소드라고 한다. 자바스크립트에서는 거의 모든 것이 객체이다. 거의 모든 것의 의미는 Number, String, Boolean, undefined를 제외하고 이다. null은 객체로 취급되지는 않지만 typeof에서는 객체로 리턴된다.


1. 객체의 생성

 자바나 C++은 클래스를 정의하고 인스턴스를 생성하는 과정에서 객체가 만들어진다. 자바스크립트는 클래스 개념이 없으며 객체 리터럴 또는 함수 생성자 방식으로 객체를 생성한다. 객체 생성 방법은 1) Object() 생성자 이용, 2) 객체 리터럴을 이용하는 방법, 3) 생성자 함수를 이용하는 방법 등이 있다. 일반적으로 객체 리터럴을 이용하면 된다.


1.1 Object() 생성자 이용

 다음과 같이 Object() 생성자 함수를 통해서 객체 생성이 가능하다. 속성은 . 이나 [] 로 설정 또는 접근 가능하다.

> var obj=new Object()

undefined

> obj.name='object'

'object'

> obj['job']='programmer'

'programmer'

> obj

{ name: 'object', job: 'programmer' }

> obj['name']

'object'

> obj.job

'programmer'

>  


1.2 객체 리터럴 이용

 객체 리터럴 방법은 객체를 생성하는 매우 간단하고 표현력 있는 방법이다. 자바스크립트에서는 {} 을 이용해서 객체를 생성할 수 있다. {와 } 사이에 이름:값 형태로 정의하고 속성들은 , 로 구별해서 선언 가능하다.

> var obj2={

... name:'object2',

... job:'designer'

... }

undefined

> obj2.name

'object2'

> obj2['job']

'designer'

>  


1.3 생성자 함수 이용

 함수를 통해서 자바스크립트 객체를 생성하는 방법이다. 함수 객체를 생성하고 new 키워드를 통해서 함수를 실행하게 되면 자바스크립트는 빈 객체를 생성하고 함수를 호출하면서 빈 객체를 this 키워드로 전달하게 된다. 자세한 것은 함수 편에서설명한다.

> function obj3(){

... this.name='object3';

... this.job='manager';

... }

undefined

> var obj=new obj3();

undefined

> obj.name;

'object3'

> obj['job']

'manager'

>  


1.4 객체 관련 명령어들

1) for in : 객체의 속성 출력

 for in 문을 사용하면 객체에 포함된 모든 프로퍼티에 대해서 추출할 수 있다. 

> for (prop in obj) {

... console.log(prop, obj[prop]);

... }

name object3

job manager

undefined 


2) delete : 객체 프로퍼티 삭제

 delete 연산자는 객체의 프로퍼티를 삭제한다. 하지만 객체 자체는 삭제하지 못한다. 또한 delete 는 프로토타입으로 연결된 객체의 속성에 영향을 주지 못한다.


2. 객체의 특성

2.1 참조 타입

 객체는 참조 타입이다. 객체를 다른 변수에 할당하게 되면 객체가 복사되는 것이 아니고 참조하게 된다. 위에서 생성한 obj 를 다음과 같이 다른 변수 refObj에 할당하면 refObj는 obj 객체 참조하는 변수이다. 따라서 refObj.name 을 변경하면 obj.name이 변경되고, obj.name을 변경하면 refObj.name은 변경된 값을 참조하게 된다.

 함수 호출시에 기본 데이터 타입은 값에 의한 호출이 발생하지만, 객체가 인자로 주어질 경우 참조에 의한 호출 방식으로 동작한다.

> var obj={name:'lee',job:'programmer'}

undefined

> function changeName(inObj,name){

... inObj.name=name;

... }

undefined

> changeName(obj,'kim');

undefined

> obj.name

'kim' 



2.2 객체 비교

 객체를 === 연사나로 비교할때는 그 객체의 값을 비교하는 것이 아니라 참조값을 비교한다. 즉 동일 객체를 가르켜야 true가 나타난다. 함수 생성자를 이용해서 생성한 객체의 경우 그 객체가 어떤 함수 생성자에 의해서 생성된 것인지를 판단하려면 instanceof 를 이용한다.

> function Obj(){

... this.name="lee";

... this.job="programmer";

... }

undefined

> var one=new Obj();

undefined

> var two=new Obj();

undefined

> var three={name:"lee",job:"programmer"}

undefined

> one===two

false

> var four=one

undefined

> one===four

true

> one instanceof(Obj)

true

> three instanceof(Obj)

false

>  


3. 프로토타입

 자바스크립트의 모든 객체는 자신의 부모 역활을 하는 객체와 연결되어 있다. 이런 부모 객체 역활을 하는 객체를 프로토타입 객체라고 한다. {}를 이용해서 객체 리터럴 방식으로 생성된 객체의 경우 Object.prototype 객체를 프로토타입 객체로 연결한다. ECMAScript 명세서에서는 자바스크리브는 모든 객체는 자신의 프로토타입을 가리키는 [[Prototpe]] 이라는 숨겨진 프로퍼티를 가진다고 설명되어 있다. node.js에서는 [[prototype]]을 볼수 없다. 하지만 크롬 프라우저의 console에서는 console.dir로 숨겨진 프로퍼티도 볼수 있다. 다음은 그 예이다.


 크롬브라우저에서 obj는 Object인데 job, name과 더불어 __proto__ 객체를 속성으로 가진다 이때 __proto__는 Object.prototype임을 알수가 있고 Object.prototype에는 기본 메소드들 toString(), hasOwnProperty() 등이 정의되어 있음을 알 수 있다. 이 객체개 왜 prototype인지는 constructor로 function Object() 함수를 가지고 있는 것을 보면 알 수 있다. (함수 객체는 자신을 constructor 속성으로 참조하고 있는 prototype객체를 가진다. 여기에서의 prototype은 [[prototype]]과는 다른 것이다.)

 자바스크립트에서는 객체를 생성할 때 결정된 프로토타입 객체는 다른 객체로 변경 가능하다. 다시 말해 부모 객체를동적으로 바꿀 수 있다.


4. 배열

 배열은 자바스크립트 객체의 특별한 형태다. 원래 다른 언어에서의 배열은 해당 항목의 오프셋(정수값)을 통해 목록을 접근할 수 있는 메모리 할당이다. 속도가 빠른데, 자바스크립트는 그렇지 않다. 자바스크립트는 배열 같은 특성을 지닌 객체를 제공하고 사전 정의된 필요한 메소드들을 제공한다. 정수로 아이템에 접근한다는 점을 제외하고는 객체와 동일하다.


4.1 배열 리터럴

 새로운 배열을 만들 때 객체 리터럴 [] 을 이용한다. 첫번째 속성은 0 이다. 배열을 생성하면 배열은 Array.prototype을 [[prototype]] 속성으로 가진다. 배열을 생성하면 기본적으로 제공되는 메소드들은 이 Array.prototype에서 정의되어 있는 것이다. 배열 객체는 length 속성을 가진다. 배열의 아이템은 어떤 데이터 타입을 가져도 상관 없다.

 arrayEx는 length가 3인 객체로, index 2의 아이템은 배열을 가지고 있다. [[prototype]]은 Array.prototype을 가르키고 있으며 배열과 관련된 여러 함수들을 이용할 수 있다.

 typeof 를 배열에 적용해 보면 Array가 아니라 Object로 나타난다. 객체와 배열의 차이는 배열은 Array.prototype을 [[prototype]]으로 가르키고 length라는 속성을 지니고 있다는 것이다. 아래처럼 객체도 '0', '1', '2' 형태로 숫자에 대하여 키:값을 정의하게 되면 배열처러 [0], [1], [2] 로 접근 가능하지만 length 속성과 Array.prototype의 함수 이용 가능 여부가 배열과 객체의 차이를 만들어 준다.

> var array=[1,2,3,4]

undefined

> var pseudo={'0':1,'1':2,'2':3,'3':4}

undefined

> pseudo[0]

1

> pseudo[1]

2

> array[0]

1

> array[1]

2

> pseudo.push(5)

TypeError: pseudo.push is not a function

    at repl:1:8

    at REPLServer.defaultEval (repl.js:262:27)

    at bound (domain.js:287:14)

    at REPLServer.runBound [as eval] (domain.js:300:12)

    at REPLServer.<anonymous> (repl.js:431:12)

    at emitOne (events.js:82:20)

    at REPLServer.emit (events.js:169:7)

    at REPLServer.Interface._onLine (readline.js:211:10)

    at REPLServer.Interface._line (readline.js:550:8)

    at REPLServer.Interface._ttyWrite (readline.js:827:14)

> array.push(5)

5

> array

[ 1, 2, 3, 4, 5 ]

> pseudo

{ '0': 1, '1': 2, '2': 3, '3': 4 } 


 배열 또한 객체의 한 종류이므로, 배열에 속성을 동적으로 추가하는 것은 가능하다. 배열에 속성을 추가한다 하더라도 배열에서 숫자로 접근하는 아이템은 바뀌지 않는다. (즉 length값은 바뀌지 않는다) 

 배열을 for in 문에 적용하게 되면 배열의 아이템과 배열의 속성값이 모두 열거 된다. 이는 배열의 아이템들만을 열거하기 위해서 좋은 방법이 아니며 for 문을 이용하는게 바람직하다.

> var array=[1,2,3];

undefined

> array.name='hello'

'hello'

> for(prop in array){ console.log(prop,array[prop]);}

0 1

1 2

2 3

name hello

undefined

> for(var i=0;i<array.length;i++){console.log(i,array[i])}

0 1

1 2

2 3

undefined 



4.2 length 속성

 length 배열의 아이템 개수인데, 다른 언어들과는 달리 배열의 길이는 상계 기반이 아니다. 즉 배열 경계 오류가 발생하지 않는다. 다시 말해 var exArray[] 로 선언하고 exArray[999]=1 로 1000번째 아이템을 설정할수 있다. 이떄 exArray.length=1000이 된다.  배열은 가장큰 인덱스에 1을 더한 값으로 보면 된다.

 length는 임으로 설정이 가능하다. 현재 가지고 있는 아이템보다 큰 범위로 설정하여도 아무런 문제가 되지 않는다. 단 현재 length보다 적은 값을 설정하게 되면 설정하는 값보다 크거나 같은 아이템은 모두 삭제 된다.

> var exArray=[1,2,3,4,5,6]undefined

> exArray.length

6

> exArray.length=10

10

> exArray

[ 1, 2, 3, 4, 5, 6, , , ,  ]

> exArray.length=3

3

> exArray

[ 1, 2, 3 ]

> delete exArray[0]

true

> exArray

[ , 23 ]

 그림은 length의 작용에 대해서 잘 설명해 준다.


4.3 삭제

 배열 요소를 삭제하는데 delete 연산자를 사용할 수 있다. delete는 특정 부분의 요소를 삭제할수 있고 해당 요소는 undefined로 대체된다. 배열을 삭제하고 나머지 요소로 대체하고 싶으면 splice라는 메소드를 사용한다.


4.4 Array 생성자

 배열은 Array() 생성자 함수로 배열을 생성할 수 있다. 이 생성자 함수는 반드시 new 와 같이 사용해야 한다. Array 생성자 호출시 파라미터가 1개이고 숫자인 경우 해당 파라미터의 수와 같은 length를 가진 빈 배열을 생성하게 되고 그 외의 경우에는 호출된 인자를 요소로 같는 배열을 생성한다. Array생성자 함수를 사용하는 것보다 [] 리터럴을 사용하는 것이 좋다.


4.5 유사 배열 객체

 유사배열 객체는 length 프로퍼티를 가지고 있는 객체를 말한다. 유사 배열 객체는 Array가 기본적으로 제공하는 메소드들을 바로 적용할 수 없지만, call(), apply() 메소드를 이용해서 유사 객체에 배열 메소드를 사용할 수 있다. 이는 특정 메소드에 파라미터로 입력받은 객체를 this로 바인딩하여 호출하게 하는 방법이다.

> var pseudo={'0':1,'1':2,'2':3}

undefined

> pseudo.length=3

3

> Array.prototype.push.apply(pseudo,[4])

4

> pseudo

{ '0': 1, '1': 2, '2': 3, '3': 4, length: 4 }

> Array.prototype.push.call(pseudo,[5])

5

> pseudo

{ '0': 1, '1': 2, '2': 3, '3': 4, '4': [ 5 ], length: 5 }

> Array.prototype.push.call(pseudo,5)

6

> pseudo

{ '0': 1, '1': 2, '2': 3, '3': 4, '4': [ 5 ], '5': 5, length: 6 } 

 배열인지 확인하기 위해서는 typeof를 로 객체인지를 확인해야 할 뿐만 아니라 constructor가 Array인지 확인해야 한다. ( if(my_value && typeof my_value==='object' && my_value.constructor===Array) )



5. 기본타입의 표준 메소드

 자바스크립트는 숫자, 문자열, 불리언 값에 대하여 각 타입별로 호출 가능한 표준 메서드들을 제공한다. 이는 기본 값들에 대해서 객체 형태로 메서드를 호출할 경우, 이들 기본값은 메서드 처리 순간에 객체로 변환된 다음 각 타입별 표준 메서드를 호출하게 된다. 메서드 호출이 끝나면 기본 값으로 복귀하게 된다.

> var basicstr='hello'

undefined

> basicstr.charAt(2)

'l'

> var basicnum=0.5

undefined

> basicnum.toExponential(1)

'5.0e-1' 


참고자료

 - 더글라스 크락포드의 자바스크립트 핵심 가이드, 한빛미디어, 2008

 - 인사이드 자바스크립트, 한빛 미디어, 2014

반응형
Posted by alias
,