자바스크립트 완벽 가이드/ 객체와 배열

객체 생성하기

객체는 복합 타입(composite datatype)이다. 즉, 객체는 여러 값들을 결합한 것으로서 각 값에 붙은 이름을 사용하여 원하는 값을 저장하고 읽어올 수 있다. 다시 말하면 객체는 이름과 값으로 구성된 프로퍼티들의 집합이라고 할 수 있다. 객체로 결합되는 값들은 숫자나 문자열 같은 기본 타입이거나, 또 다른 객체일 수도 있다.

객체를 생성하는 가장 쉬운 방법은 객체 리터럴을 사용하는 것이다. 객체 리터럴이란 중괄호 { } 안에 이름과 값을 한 쌍으로 하는 프로퍼티들을 콤마로 분리하여 연결한 리스트다.

var empty = { }; // 객체 empty는 아무런 프로퍼티도 가지고 있지 않다.
var point = { x:0, y:0 };
var circle = { x:point.x, y:point.y+1, radius:2 };
var homer = {
"name": "Homer Simpson",
"age": 34,
"married": true,
"occupation": "plant operator",
'email': "homer@example.com"
};

객체 리터럴은 자바스크립트 표현식으로서 평가될 때마다 새로운 객체를 생성하고 초기화한다. 즉, 객체 리터럴이 루프 안에서 반복적으로 호출되는 함수 내에 있다면, 이 객체 리터럴은 비록 하나이지만 복수의 새로운 객체를 생성해 낼 수 있다.

new 연산자를 사용하면 다른 방식으로 객체를 사용할 수 있다. new 연산자의 뒤에는 객체의 프로퍼티들을 초기화하는 생성자 함수의 호출이 뒤따라야 한다.

var a = new Array( );
var d = new Date( );
var r = new RegExp("javascirpt", "i");

객체 프로퍼티

객체 프로퍼티에 접근하기 위해서는 마침표(.) 연산자를 사용하며, 접근하려는 프로퍼티를 소유한 객체가 이 연산자의 좌측에 위치한다. 객체의 프로퍼티들은 변수와 유사한 방식으로 사용할 수 있다. 즉, 프로퍼티에 값을 저장하거나 혹은 프로퍼티에서 값을 읽어올 수 있다.

var book { };

book.title = "Javascript: The Definitive Guide";
book.chapter1 = new Object( );
book.chapter1.title = "Introduction to Javascript";
book.chatper1.pages = 11;
book.chapter2 = { title: "Lexial Structure", pages: 6 };

alert("Outline: " + book.title + "<br>n<br>t" + "chapter 1 " + book.chapter1.title + "<br>n<br>t" + "chapter 2 " + book.chapter2.title);

변수를 선언하기 위해서는 var 키워드를 사용하지만, 객체의 프로퍼티에는 var 키워드를 사용하지 않아도 되며 사실 사용할 수도 없다. 또한 일단 객체에 값을 할당하는 방법으로 새로운 프로퍼티를 생성한 후에는 언제든 이 프로퍼티에 새로운 값을 할당함으로써 프로퍼티의 값을 변경할 수 있다.

프로퍼티 열거하기

for/ in 루프를 사용하여 객체 프로퍼티들을 열거하거나, 객체의 각 프로퍼티에 대한 작업을 반복적으로 수행할 수 있다.

var names = "";
for(var name in obj) names += name + '<br>n';
alert(names);

프로퍼티 존재 확인하기

in 연산자를 사용하면 프로퍼티의 존재 여부를 확인할 수 있다.

in ( "x" in o) o.x = 1;

프로퍼티 삭제하기

객체의 프로퍼티를 삭제하기 위해서는 delete 연산자를 사용한다.

delete book.chapter2;

프로퍼티를 삭제하는 것은 단순히 값을 없애는 것이 아니라 실제로 객체에서 프로퍼티를 완전히 제거하는 것이기 때문에 for/ in 루프나 in 연산자로 삭제된 프로퍼티를 찾을 수 없다.

연관 배열로서의 객체

배열에서 주로 사용하는 [ ] 연산자를 사용해도 객체의 프로퍼티에 접근할 수 있다. 아래의 표현식은 완전히 동일하다.

object.property
object["property"]

마침표(.)를 이용해서 프로퍼티에 접근할 수도 있지만, 접근해야 할 객체의 이름을 사용자에게 받는 것과 같이 미리 알 수 없는 경우 [ ] 연산자를 이용하여 프로그램을 작성한다.

var stock_name = get_stock_name_from_user( );
// 사용자에게 주식 이름 입력 받기 
var shares = get_number_of_shares( );
// 사용자에게 주식의 수 입력 받기 
portfolio[stock_name] = shares; // 포트폴리오에 받아온 주식 이름의 프로퍼티를 만들고 거기에 주식의 가격을 넣어라

이러한 방식으로 객체를 사용할 때 이를 연관 배열(associative array)이라 한다. 자바스크립트 문장의 진정한 힘은 for/ in 루프와 연관배열을 함께 사용할 때 분명해진다. 아래의 예는 사용자가 포트폴리오를 모두 입력한 후, 현재 총액을 계산하기 위한 코드이다.

var value = 0;
for (stock in portfolio) {
    // 주식의 가격 * 주식의 수를 곱한 것을 계속 value에 더하는 식. 앞선 식에서 portfoli[stock]에 주식의 수를 넣어 놨다. 
    value += get_share_value(stock) * portfolio[stock];
}

주식의 이름을 미리 알아낼 방법이 전혀 없기 때문에, 이 코드는 for/ in 루프를 사용해서만 작성할 수 있다. 즉 portfolio 같은 연관배열의 프로퍼티 이름을 열거해 낼 수 있는 유일한 방법이 바로 for/ in 루프이다.

공통적으로 나타나는 객체 프로퍼티와 메서드

자바스크립트의 모든 객체는 Object 클래스를 상속한다. 따라서 모든 객체는 Object에서 상속받은 프로퍼티와 메서드를 갖고 있다.

Constructor 프로퍼티 객체를 초기화하는데 사용되는 생성자 함수. 예를 들어 Date( ) 생성자를 사용하여 객체 d를 생성했다면 d.constructor 프로퍼티는 Date를 가리킨다. constructor 프로퍼티는 객체의 타입을 판단하는데 사용될 수 있다.
toString( ) 메서드 별도의 전달인자 없이 호출되며, 메서드를 호출한 객체의 값을 어떠한 방식으로든 표현하는 문자열을 만들어 결과로 반환한다.
toLocaleString( ) 메서드 이 메서드의 목적은 객체의 지역화(localized)된 문자열 표현을 제공하기 위함이다. Object 클래스에 의하여 기본으로 제공되는 toLocalString( ) 메서드는 그 자체로는 어떠한 지역화 작업을 행하지 않기 때문에 반환하는 값은 toString( )과 같다. 그러나 Object 클래스의 서브 클래스들은 자신들만의 고유한 toLocalString( ) 메서드를 정의할 수 있다.
valueOf( ) 메서드 이 메서드는 자바스크립트가 객체를 문자열이 아니라 숫자 같은 다른 기본 타입으로 변환하려 할 때 호출된다. 즉, 객체가 기본 타입 값을 필요로 하는 문맥 안에서 사용될 때, 자바스크립트는 valueOf( ) 메서드를 자동으로 호출한다.
hasOwnProperty( ) 메서드 이 메서드는 프로퍼티의 이름을 담는 한 개의 문자열 전달인자를 받아서 객체가 이 프로퍼티를 소유하고 있는지 검사한다. 프로퍼티가 상속받은 것이 아니고 객체 안에 지역적으로 정의되어 존재한다면 true를 반환하고 그렇지 않으면 false를 반환한다.
propertyIsEnumerable( ) 메서드 프로퍼티의 이름을 담은 문자열 전달인자를 하나 받아서, 이 이름의 프로퍼티를 객체가 상속받지 않고 직접 지역적으로 정의했는지 검사한다. 나아가 이 프로퍼티가 for/ in 루프를 사용하여 열거될 수 있는 것인지 검사한다. 이 모든 조건을 충족하면 true, 그렇지 않으면 false를 반환한다.
isPrototypeOf( ) 메서드 이 메서드의 객체가 전달인자로 주어진 객체의 프로토타입 객체라면 true, 그렇지 않으면 false를 반환한다.

배열

배열은 순서 있는 값들의 집합이다. 배열 안의 각 값을 원소라 부르며 각 원소는 배열 안에서 그 위치를 가리키는 번호를 할당 받는데 이 번호를 인덱스(index)라 한다. 자바스크립트는 타입이 고정되지 않은 언어(untyped language)기 때문에 같은 배열의 각 원소는 서로 다른 임의의 타입을 가질 수 있다. 또한 배열은 다른 배열을 원소로 가질 수도 있기 때문에, 배열의 배열과 같은 자료구조를 생성할 수 있다. 배열은 추가 기능을 아주 조금 지닌 객체에 지나지 않는다.

배열 리터럴을 사용하면 가장 쉽게 배열을 생성할 수 있다.

var empty = [ ];
var primes = [2, 3, 5, 7, 11];
var misc = [1.1, true, "a", ];

배열 리터럴에는 상수 뿐만 아니라 임의의 표현식도 사용할 수 있다.

var base = 1024;
var table = [base, base+1, base+2, base+3];

배열 리터럴은 객체 리터럴이나 또 다른 배열 리터럴을 포함할 수 있다.

var b = [ [1, { x:1, y:2 } ], [2, { x:3, y:4} ] ];

배열 리터럴의 첫 번째 값은 새롭게 생성된 배열의 0번 인덱스에 저장되며 두 번째 값부터는 배열의 1번 인덱스부터 차례대로 저장된다. 배열 리터럴의 콤마 사이에 아무것도 적지 않으면 정의되지 않은 원소가 생성된다.

var count = [1, , 3]; // 3개의 원소를 가진 배열, 가운데 원소는 정의되지 않음
var undefs = [ , , ]; // 2개의 배열을 가진 배열, 1, 2번 원소는 정의되지 않음

배열을 생성하는 또 다른 방법은 Array( ) 생성자를 사용하는 것이다. 이 생성자는 세 가지 다른 방법으로 호출할 수 있다.

  • 전달인자 없이 호출하는 방법
    • var a = new Array( ); %%//%% 배열 리터럴 [ ]와 같이 아무 원소도 없는 빈 배열을 생성한다.
  • 명시적으로 배열의 처음 n개의 원소를 정의하며 호출하는 방법
    • var a = new Array( 5, 4, 3, 2, 1, “testing, testing” );
  • 배열의 길이를 지정하는 숫자 값을 전달인자로 하여 호출하는 방법
    • var a = new Array(10);

배열 원소 읽고 쓰기

배열의 각 원소에 접근할 때는 [ ] 연산자를 사용한다. [ ] 연산자의 좌측에는 배열에 대한 참조가 위치해야 하며, ‘ [ ‘ 와 ‘ ] ‘ 사이에는 음수가 아닌 정수 값으로 평가되는 임의의 표현식이 위치할 수 있다.

value = a[0];
a[1] = 3.14;
i = 2;
a[i] = 3;
a[i+1] = "hello";
a[a[i]] = a[0];

배열은 객체의 특별한 종류이기 때문에 . 또는 [ ] 구문을 사용하여 배열 안에 숫자가 아닌 이름의 객체 프로퍼티를 정의하고 접근할 수 있다. 배열의 인덱스에는 반드시 0보다 크거나 같고 232-1 보다 작은 정수를 사용해야만 한다.

배열에 새로운 원소 추가하기

자바스크립트의 배열은 임의 개수의 원소를 가질 수 있으며 원소의 개수는 언제든 변경할 수 있다. 배열에 새로운 원소를 추가하려면 그 값을 할당하기만 하면 된다.

a[10] = 10;

자바스크립트 배열의 인덱스는 연속적이지 않아도 된다. 자바스크립트는 배열에 실제로 저장된 원소들에 대해서만 메모리를 할당하도록 구현할 수 있다. 즉, 자바스크립트 인터프리터는 원소가 있는 인덱스를 위해서만 메모리를 할당하며, 그 사이에 비어있는 인덱스에 대해서는 메모리를 할당하지 않는다.

배열 원소는 객체에도 추가될 수 있다.

var c = new Circle(1, 2, 3);
c[0] = "this is an array element of an object!"; // 이 경우 c[0]는 객체의 배열 원소가 된다.

이 예는 단지 객체에 “0” 이라는 이름의 프로퍼티를 추가할 뿐이다. 객체에 배열 원소를 추가한다고 해서 객체가 배열이 되지는 않는다.

배열 원소 삭제하기

delete 연산자를 사용하면 배열 원소의 값을 undefined 값으로 설정할 수 있다. 하지만 이렇게 하면 배열 원소 그 자체는 사라지지 않고 여전히 존재한다. 배열 원소를 배열에서 완전히 삭제하고 삭제한 배열 원소의 뒤쪽에 위치한 원소들을 앞쪽으로 옮겨서(to lower indexes) 저장하려면 배열 메서드를 사용해야만 한다. Array.shift( ) 메서드는 배열의 첫 번째 원소를 삭제하고 Array.pop( ) 메서드는 배열의 마지막 원소를 삭제하며, Array.splice( ) 메서드는 연속된 범위 안의 원소들을 일괄적으로 삭제한다.

배열의 길이

Array( ) 생성자 혹은 배열 리터럴 등의 방법으로 사용하여 생성된 모든 배열에는 이 배열에 있는 원소의 수를 알려주기 위하 length라는 이름의 특별한 프로퍼티가 있다. 좀 더 정확히 말하자면 배열은 정의되지 않은 원소도 가질 수 있기 때문에 length 프로퍼티는 배열 안에서 가장 큰 인덱스 값보다 언제나 하나 더 큰 값이다. 일반적인 객체 프로퍼티와 달리, length 프로퍼티는 배열에 새로운 요소가 추가될 때마다 위의 규칙을 만족하기 위해 자동으로 갱신된다.

배열 순회하기

length 프로퍼티의 가장 일반적인 용도는 배열의 모든 원소를 순회하는 작업이다.

배열 크기 조절하기

배열의 length 프로퍼티는 읽고 쓸 수 있는 값이다. length 프로퍼티를 현재 값보다 작게 설정하면 배열은 그 새로운 길이로 축소된다. 즉 새롭게 설정된 배열의 길이를 벗어나는 위치의 원소들은 버려지고 그 원소들의 값은 전부 잃어버린다. length 프로퍼티를 현재의 값보다 크게 설정하면 배열의 끝 부분에 정의되지 않은 원소들이 추가되면서 배열이 새로운 길이로 늘어난다.

다차원 배열

자바스크립트는 진정한 의미에서의 다차원 배열을 지원하지는 않는다. 그러나 배열의 배열을 사용하여 효과적으로 다차원 배열을 흉내낼 수 있다. 배열의 배열 원소에 접근하기 위해서는 단순히 [ ] 연산자를 두 번 사용하면 된다. 예를 들어 matrix가 배열의 배열이라 할 때 이 배열의 특정 숫자에 접근하기 위해서는 matrix[x][y]와 같이 쓸 수 있다.

배열 메서드

[ ] 연산자 외에도 배열을 다루기 위한 다양한 종류의 메서드들이 Array 클래스 안에 정의되어 있다.

join( ) 메서드 이 메서드는 배열의 모든 원소를 문자열로 변환하고 이어 붙여서 반환한다. 결과로 반환되는 문자열에서 배열의 원소들을 구분하기 위해 구분자(separator) 문자열이 사용되는데, Array.join( )에 전달인자를 넘겨 문자열을 지정할 수 있다. 별도로 구분자 문자열을 지정하지 않으면 콤마(,)가 기본값으로 사용된다.
reverse( ) 메서드 이 메서드는 배열 안의 원소 순서를 반대로 정렬하여 반환한다. 이 작업은 배열 안에서 직접 수행된다. 즉, 순서가 뒤바뀐 새로운 배열을 생성하는 것이 아니라, 이미 존재하는 배열 안에서 원소들의 순서를 뒤바꾼다.
sort( ) 메서드 이 메서드는 배열 안의 원소들을 정렬하여 반환한다. 이 작업은 reverse( )와 마찬가지로 배열 안에서 직접 수행된다. sort( ) 메서드를 별도의 전달인자 없이 호출하면, 배열 안의 원소들을 알파벳 순으로 정렬한다.
알파벳순이 아니라 다른 순서로 배열을 정렬하려면 메서드의 전달인자를 통해 비교 함수를 직접 명시해줘야 한다. 만약 첫 번째 전달인자가 두 번째 보다 먼저 나타나야 한다면 비교 함수는 0보다 작은 숫자를 반환해야 한다. 만일 첫 번째 전달인자가 두 번째보다 뒤에 나타나야 한다면 0보다 큰 숫자를 반환해야 하며, 만약 두 값이 동등하다면 0을 반환해야 한다.
concat( ) 메서드 이 메서드는 본래 배열의 모든 원소에 concat( ) 메서드의 전달인자들을 전부 이어붙인 배열을 새롭게 생성하여 반환한다.
만약 concat( ) 메서드의 전달인자로 배열을 전달하면, 이 배열 안의 원소들을 꺼내어 반환하는 배열에 이어 붙인다. 그러나 중복하여 중첩된 배열은, 그 배열에 속한 배열의 원소를 분래해내지 않음에 주의하라.var a = [1, 2, 3] a.concat(4, 5); %%//%% [1, 2, 3, 4, 5]를 반환
a.concat( [4, 5] ); %%//%% [1, 2, 3, 4, 5]를 반환
a.concat( [4, 5], [6, 7] ); %%//%% [1, 2, 3, 4, 5, 6, 7]를 반환
a. concat(4, [ 5, [6, 7] ] ); %%//%% [1, 2, 3, 4, 5, [6, 7]]를 반환
slice( ) 메서드 이 메서드는 배열의 일부분(slice) 혹은 부분 배열(subarray)을 반환한다.
slice( ) 메서드는 전달인자를 두 개 받는데, 각 인자는 반환될 부분의 처음과 끝을 각각 명시한다. 반환되는 배열은 첫 번째 전달인자가 지정하는 위치부터 두 번째 전달인자가 지정하는 위치를 제외한 그 사이의 모든 원소를 포함한다.
만약 전달인자를 하나만 명시하면, 그 위치에서 배열 끝까지의 모든 원소를 포함하는 부분 배열을 반환한다.만약 전달인자가 음수라면, 배열의 마지막 원소에서 상대적인 위치로 배열의 원소들을 지정한다. 예컨대 -1이면 마지막 원소를 가리키며, -3이면 마지막에서 앞의 3번째 원소를 가리킨다.
splice( ) 메서드 이 메서드는 배열에 원소를 삽입하거나 원소를 제거하려 할 때 범용적으로 사용할 수 있는 메서드다. 이러한 변경 작업은 배열 안에서 직접 수행된다.
즉, splice( ) 메서드는 slice( )나 concat( )과 달리 새로운 배열을 만들어 반환하지 않는다. splice( )는 배열에서 원소를 삭제하거나 배열에 새로운 원소를 삽입하는데 사용할 수 있으며 이러한 작업을 동시에 수행할 수도 있다. 삭제와 삽입 작업으로 변형된 배열 안에서도 배열 원소들이 연속선상에 분포하게 하기 위해서, 필요에 따라 원소들의 이동작업이 일어날 수 있다.
splice( )의 첫 번째 전달인자는 배열 상에서 삽입 혹은 삭제 작업이 시작하게 될 위치를 지정하며, 두 번째 전달인자는 배열에서 삭제할(잘라낼) 원소들의 개수를 지정한다. 두 번째 전달인자를 지정하지 않으면 첫 번째 전달인자로 지정한 작업의 시작 위치에서 배열의 마지막 원소까지를 전부 잘라낸다.
push( )와 pop( ) 메서드 이 메서드들을 사용하면 배열을 마치 스택인 것처럼 조작할 수 있다.
push( )는 하나 혹은 그 이상의 원소들을 배열의 끝 부분에 이어 붙이고 배열의 새로운 길이를 반환한다. pop( ) 메서드는 배열의 마지막 원소를 제거하고 배열의 길이를 감소시킨 후 배열에서 제거한 원소를 반환한다. 이 두 메서드는 새로운 배열을 만들지 않고 배열 그 자체를 변화시킴에 유의하라. push( )와 pop( )을 함께 사용하면 자바스크립트 패열로 FILO(First-in, Last-out) 스택을 구현할 수 있다.var stack = [ ];
stack.push(1, 2); %%//%% push는 길이를 반환하므로 2를 반환
stack.pop( ); %%//%% pop( )은 제거한 원소를 반환하므로 2를 반환
stack.push( [4, 5] ); %%//%% push는 배열의 길이를 반환하므로 2를 반환
stack.pop( ); %%//%% pop( )은 제거한 원소를 반환하므로 [4, 5]를 반환한다.
unshift( )와 shift( ) 메서드 이 메서드들은 push( ), pop( )과 매우 유사하게 작동하는데, 배열의 끝이 아니라 배열의 맨 앞에서 원소를 삽입하고 제거한다는 점이 다르다.
unshift( )는 하나 혹은 그 이상의 원소들을 배열의 맨 앞에 삽입한다. shift( )는 배열의 첫 번째 원소를 제거한 후, 나머지 배열 원소들을 전부 앞으로 옮겨 빈 공간을 메우고 배열에서 제거한 원소를 반환한다.var a = [ ]; a.unshift(1); %%//%% unshift( )는 배열의 길이를 반환하므로 1을 반환
a.unshift(22); %%//%% unshift( )는 배열의 길이를 반환하므로 2를 반환
a.shift( ); %%//%% shift( )는 제거한 원소를 반환하므로 22를 반환
toString( )과 toLocaleString( ) 메서드 배열에는 다른 자바스크립트 객체와 마찬가지로 toString( ) 메서드가 있다. 배열의 toString( ) 메서드는 우선 배열의 모든 원소를 문자열로 변형하고 이 문자열들을 콤마(,)로 분리한 목록을 반환한다. 결과 문자열은 대괄호 [ ] 문자나 배열 값들을 둘러싼 다른 종류의 구분자들을 포함하지 않는다.

[1, 2, 3].toString( ); %%//%% 결과는 1, 2, 3
[“a”, “b”, “c”].toSting( ); %%//%% 결과는 a, b, c
[1, [2, ‘c’] ].toString( ); %%//%% 결과는 1, 2, c

toLocaleString( )은 toString( )의 지역화된 버전이다. 이 메서드는 우선 배열의 각 원소들을 그 원소의 toLocaleString( ) 메서드를 사용하여 변환하고, 지역에 특화되었거나 구현에 정의된 구분자 문자열을 사용하여 각 결과 문자열을 연결한다.

[ssba]

The author

지성을 추구하는 디자이너/ suyeongpark@abyne.com

댓글 남기기

This site uses Akismet to reduce spam. Learn how your comment data is processed.