1. toString() 메서드
toString()에 깔려있는 기본 아이디어는 객체의 각 클래스가 자신을 문자열로 표현할 수 있게 만드는 것이데, 이를 위해서 객체를 문자열 형태로 변호나할 수 있게 적절한 toString() 메서드가 정의되어야 한다.
여러분이 하나의 클래스를 정의하면 클래스의 인스턴스가 문자열로 변환될 수 있게 반드시 toString() 메서드를 정의해야 한다. 이 문자열에는 변환되는 객체에 대한 정보가 들어있어야 하는데, 이렇게 해두면 나중에
디버깅할 때 유용하게 사용할 수 있다. 뿐만 아니라, 문자열이 적당하게 구성되면 그 자체만으로도 프로그램 내에서 유용한 정보가 될 수 있다. 또한, toString()을 사용해 변환한 문자열을 다시 객체 형태로 바꾸기 위해 static parse()메서드를 추가하는 것도 고려할 수 있다.
예9-2에 있는 Complex 클래스에는 toString() 메서드가 구현되어 있는데,
다음 코드같이 Circle 클래스에도 toString() 메서드를 정의할 수 있다.
이 toString() 메서드를 사용하면 Circle 클래스의 객체는 '[Circle of radius 1, centered at(0,0).]"과 같은 문자열로 변환된다.
2. valueOf() 메서드
valueOf() 메서드는 toString()과 상당히 유사하지만, 자바스크립트가 객체를 Number 같은 문자열 외의
기본 타입으로 변환하려 할 때 호출하게 된다. 할 수 있는 한 이 함수는 this 키워드가 참조하고 있는 객체의 값을 나타낼 수 있는 기본 타입의 값을 반환해야 한다.
정의에 따르면 객체는 기본 타입의 값이 아니기 때문에 일치하는 기본 타입이 없다.
따라서 Object 클래스가 정의하는 기본적인 valueOf()는 아무런 변환도 수행하지 않으며 단순히 valueOf()를 호출한 객체를 반환한다. Number와 Boolean같은 클래스들은 일치하는 기본 타입이 있기 때문에 valueOf() 메서드를 재정의(override)하여 적절한 기본 타입의 값을 반환한다.
이런 이유 때문에 Number와 Boolean 객체가 서로 같은 기본 타입의 값인 것처럼 작동한다.
경우에 따라서 여러분은 동등한 기본 타입이 존재하는 클래스를 정의하게 될 것이다.
이때 여러분은 이 클래스에 valueOf() 메서드를 새롭게 정의하고 싶을 것이다.
예 9-2에 있는 Complex 클래스에는 valueOf() 메서드가 정의되어 있는데 이 메서드는 복소수의 실수부에
해당하는 값을 반환한다. 즉, Complex 객체가 숫자로 이루어진 문맥에서 사용될 때는 이 객체가 허수부가
없는 실수인 것처럼 작동한다.
예를 들어, 다음 코드를 살펴보자.
var b = new Complex(2,1);
var c = Complex.sum(a,b); // c는 복소수{7,5}다.
var d = a + b; // d는 숫자 7이다.
valueOf() 메서드를 정의할 때 주의해야 할 사항이 하나 있다.
어떤 경우에는 객체를 문자열로 변환할 때 toString() 메서드보다 valueOf() 메서드의 우선순위가 더 높아진다. 따라서 여러분이 클래스에 valueOf() 메서드를 정의해 놓았다면 객체를 문자열로 바꾸고 싶을 때
toString() 메서드를 명시적으로 써주어야 한다. Complex 예를 보며 계속 생각해 보자.
alert!("c = " + c.toString()); // 화면에는 'c = {7,5}'가 표시된다.
3. 비교 메서드
자바스크립트의 동등 연산자는 값이 아닌 참조를 통해 객체를 비교한다.
즉 두 객체의 참조가 주어졌을 때 이 연산자들은 두 참조가 같은 객체를 가리키는지 검사한다.
서로 다른 두 객체에 같은 이름을 가진 프로퍼티가 있고 이 프로퍼티의 값이 같은지를 검사하는 것이 아니다.
가끔 두 객체가 동등한지 또는 상대적인 순서는 어떻게 되는지(<와 > 연산자가 하듯이)를 검사하는 것이
유용할 때가 있다. 만약 여러분이 클래스를 정의하고 이 클래스의 인스턴스들을 비교하고 싶다면
이를 위해 적절한 메서드들을 정의해야만 한다.
자바 프로그램 언어는 객체를 비교하기 위해 메서드를 사용하는데 자바스크립트에서도 이를 따르는 것이
일반적이며 유용한 방법이다. 여러분이 만든 클래스의 인스턴스들이 서로 동등한지를 검사할 수 있게 하려면 equals()라는 인스턴스 메서드를 정의하라. 이 메서드는 한 개의 전달인자를 받고 전달인자와 이 메서드를
호출한 객체가 동등하면 참을 반환해야 한다. 당연히 '동등'이 의미하는 바는 여러분의 클래스의 내용에
따라서 여러분이 정의하기에 달려있다.
일반적으로 많은 사람들은 간단히 두 객체의 인스턴스 프로퍼티들이 서로 같은 값인지 검사하게 만든다.
예9-2에 있는 Complex 클래스에는 이런 관점에서 만들어진 equals() 메서드가 있다.
객체를 비교할 때 객체 간의 어떤 순서를 비교하는 것이 유용할 수도 있다.
즉, 한 인스턴스가 다른 인스턴스에 비해 '작다' 혹은 '크다'라고 말할 수 있다. 예를 들어, Complex 클래스의 인스턴스들을 magnitude()에 따라 순서를 매길 수 있다. 반면 Circle 객체의 순서를 정하는 것은 좀 애매하다. 반지름에 따라서 ? X, Y좌표에 따라? 아니면 이들을 조합하여?
만약 여러분이 객체를 <나 <= 같은 관계 연산자와 함께 사용하려면 자바스크립트는 우선 객체의 valueOf()
메서드를 호출한 후 이 메서드가 기본 타입의 값을 반환하면 이 값을 비교한다.
우리가 만든 Complex 클래스에는 복소수의 실수 부분을 반환해주는 valueOf 메서드가 있기 때문에 Complex 클래스의 인스턴스는 마치 실수인 것처럼 비교할 수 있다. 이것은 여러분들이 원하던 것일 수도
있고 아닐수도 있다. 여러분이 원하는 순서대로 객체를 비교하기 위해서는 compareTo() 메서드
(이것 역시 자바의 방법을 따른다)를 사용할 수 있다.
compareTo() 메서드는 한 개의 전달인자를 받아들이고 메서드를 호출한 객체와 전달인자를 비교한다.
만약 객체가 전달인자보다 작으면 compareTo()는 0보다 작은 값을 반환해야 한다.
마지막으로 객체와 전달인자가 같으면 0을 반환해야 한다.
이 관습을 사용할 때는 반환되는 값이 아주 중요하며, 이를 통해 다음과 같은 관게 연산자와 동등 연산자에
대한 표현식을 대체할 수 있다.
이것을 | 이렇게 바꾼다. |
a < b | a.compareTo(b) < 0 |
a <= b | a.compareTo(b) <= 0 |
a > b | a.compareTo(b) > 0 |
a >= b | a.compareTo(b) >= 0 |
a == b | a.compareTo(b) == 0 |
a != b | a.compareTo(b) != 0 |
다음은 예9-2에 있는 Complex 클래스의 크기(magnitude)를 사용하여 복소수를 비교하는 compareTo()
메서드다.
// 발생시킨다. 다른 방법으로, 이와 같은 경우에 -1이나 1을 반환하여 모든 복소수가
// 다른 값보다 크거나 작게 만든다.
if (!that || !that.magnitude || typeof that.magnitude != "function")
// 이 방식은 compareTo() 메서드를 구현할 때 자주 유용하게 사용할 수 있다.
return this.magnitude() - that.magnitude();
클래스의 인스턴스를 비교하는 한 가지 이유는 인스턴스들을 배열로 만들어 저장할 때 순서를 매길 수 있기 때문이다. Array.sort() 메서드는 compareTo() 메서드와 반환값이 같은 함수를 전달인자로 받아서 비교할 때 사용하기도 한다. 아래에 있는 코드같이 compareTo() 메서드가 주어지면 Complex 객체의 배열을 쉽게 정렬할 수 있다.
정렬을 위해서 static compare() 메서드를 compareTo() 인스턴스 메서드가 정의되어 있는 클래스에 집어넣는 것을 고려할 수 있다. 이 중 하나의 메서드는 나머지 하나의 메서드를 사용하여 쉽게 정의할 수 있다.
예를 들자면,
예 9-2에 있는 Complex 클래스에 원래는 compareTo()와 compare() 메서드가 포함되어 있지 않다는 사실을 주목하라. 이는 예 9-2에 있는 equals() 메서드와 의미가 일치하지 않기 때문이다. equals() 메서드는 두 Complex 객체의 실수부 값과 허수부 값이 서로 같을 때만 두 객체가 같다고 말한다. 반면 compareTo() 메서드는 어떤 두 복소수의 크기만 같으면 0을 반호나한다. 1+0i와 0+1i는 크기가 같기 때문에 compareTo() 메서드는 두 복소수가 같다고 말하지만 equals() 메서드는 다르다고 말한다. 만약 여러분이 equals()와 compareTo() 메서드를 같은 클래스에 구현한다면 이 두 메서드의 의미가 서로 일치하게 하는 것이 좋다.
'같다'는 것에 대한 의미가 일치하지 ㅇ낳는 코드는 버그에 치명적일 수 있다.
다음은 기존의 equals() 메서드와 의미를 같게 만든 compareTo() 메서드다.
Complex.prototype.compareTo = function(that) {
if (result == 0) // 만약 같다면
// 이제 this.equals(that)와 같은 의미를 0을 만들었다.
return result;
'IT_Programming > JavaScript' 카테고리의 다른 글
[펌] How JavaScript Timers Work (0) | 2010.07.12 |
---|---|
[펌] 느긋하게 비동기식으로 JavaScript를 웹 문서에 추가하는 방법 (0) | 2010.07.09 |
자바스크립트 완벽가이드 - 9.3 자바스크립트의 클래스 시뮬레이션 (0) | 2010.07.04 |
자바스크립트 완벽가이드 - 9.2 프로토타입과 상속 (0) | 2010.07.04 |
자바스크립트 완벽가이드 - 9.1 생성자 (0) | 2010.07.04 |