클래스와 모듈
자바스크립트 완벽가이드 클래스와 모듈을 학습한다
향후 ES6에서 다루는 class 키워드를 사용한 개념을 이야기 하는 것이 아니다
무엇을 클래스와 모듈이라 취급하는지 한번 알아본다.
ES5 기준으로 설명된다.
클래스는 프로토타입 기반의 상속 메커니즘을 기반한다.
클래스와 프로토타입
두 객체가 같은 프로토타입 객체로부터 프로퍼티를 상속 받았을 때, 같은 클래스와 인스턴스로 취급한다.
동적으로 확장이 될 수 있다.
팩터리 역활을 하는 함수를 이야기 하나 쓸 일은 없을 것 같다.
대부분의 챕터에서 this keyword 의 역활을 확실히 알기를 권장한다. 이 챕터도 마찬가지..
클래스와 생성자
생성자로 내부에 수행할 변수를 초기화, 생성하는 역활을 한다.
"(정의한 객체명).prototype" 프로퍼티를 통해 상속 시키고자 하는 코드를 작성한다.
new 키워드로 생성자 함수를 호출하며 일반 함수와 차이점은 대문자로 시작해준다가 관례이나 누가 지킬까 싶기도 하다.
썩 와닿지가 않는다.
생성자와 클래스 구별
프로토타입 객체는 클래스를 구별할떄 핵심적인 역활을 한다고 써있다. 같은 프로토타입 객체를 상속한 경우에만 같은 클래스의 인스턴스라고 알아두면 된다.
instanceof 는 생성자에 의해서 초기화된건지 검증하지 않고 [프로토타입을 상속하는가 검증]하는 키워드 이다.
별도로 이 연산자에 대해서 공부할 가치가 있어보이긴 한다.
constructor 프로퍼티
prototype 프로퍼티가 있어야지만 모든 함수는 생성자가 될 수 있다. 그래서 자동으로 설정이 된다.
ES5 에서는 Function.bind() 메서드가 반환하는 함수는 자동으로 설정되지 않는다.
자동으로 설정되는 prototype property 의 값은 constructor property 하나만 가진 객체이다.
이 constructor property 는 열거되지 않고 값으로 해당 함수 객체를 가진다.
참 설명이.. 알아먹기 힘들다.
어떤 객체에 프로토타입 객체에 constructor property 가 있다는 것은
이 객체의 생성자를 가르키는 constructor property 역시 상속함을 뜻한다.
이 사실을 통해서 constructor 를 통하여 클래스를 구별하거나 객체의 클래스를 얻어낼 수 있다는 사실을 알 수 있다.
별도로 정의하는 프로토타입 객체에는 constructor 가 자동으로 생기진 않는다. 이럴경우 명시적으로 설정하여 해결이 가능한다.
혹은 이럴 필요가 없이 미리 정의된 프로토타입 객체를 확장해 나가는 식으로 진행하는 것도 하나의 방법이다.
자바 스타일 클래스
궁금했던 정보이기는 하다. 뭔 차이가 있는지 알아보려고 한다.
자바스크립트는 함수를 값으로 가질 수 있다. 그로 인해 메서드와 필드의 뚜렷한 경계선이 없다.
하지만 크게 4가지로 구분 될 수 있다.
인스턴스 필드
인스턴스 메서드
클래스 필드
클래스 메서드
클래스는 크게 다음 3가지 객체가 관련된다.
생성자 객체
클래스의 이름을 정의한다.
이 객체에 추가한 프로퍼티는 클래스 필드와 메서드가 될 수 있다.
프로토타입 객체
모든 인스턴스에 상속되는 객체이며 값으로 함수를 가진 프로퍼티는 인스턴스 메서드가 될 수 있다.
인스턴스 객체
같은 클래스를 통해 생성된 객체는 독립적이며 이 인스턴스 객체에 직접 정의한 프로퍼티는 같은 클래스의 인스턴스라
하더라도 직접적인 공유는 이루어 지지 않는다.
클래스의 정의 하는 과정의 세단계의 알고리즘은 다음과 같다.
인스턴스 프로퍼티를 설정하는 생성자 함수를 작성한다.
생성자의 프로토타입 객체에 인스턴스 메서드를 정의한다.
생성자 자체에 클래스 필드 혹은 클래스 프로퍼티를 정의한다.
위 클래스를 정의하는 세단계의 알고리즘은 까먹을 수도 있으니 클래스를 정의하기 위한 함수로 작성하여 구현하도록 한다.
ex) defineClass(constructor, instanceMethod, classProperties) {}
자바에서는 인스턴스 메서드의 인스턴스 필드를 지역변수 처럼 사용이 가능하고, this 키워드를 별도로 사용할 필요가 없다.
'with'로 비슷한 효과를 내어 흉내낼 수도 있디만 권장되지 않는 점을 알도록하자.
또한 접근제한자 같은 키워드는 자바스크립트에서 존재하지 않기 때문에 비슷한 흉내를 내는 기법도 있다.
모듈 패턴
상수 프로퍼티
클로저 지역변수
클래스 확장하기
자바스크립트의 프로토타입 기반의 상속은 동적이다. 상속받은 프로토타입이 변경이 되면 동일하게 변경이 된다.
가령 모든 객체에서 유용할 것 같아, 최상위 객체 Object 에 정의를 하는 것을 좋지 않은 방법이다.
안전하게 클래스를 확장해 나가고 싶다면 Object.defineProperty() 를 생각해보는 것도 방법이다.
그러나 실무에서는 쓸 것같지 않다. 복잡해질 뿐..
클래스와 자료형
대개는 typeof 연산자를 통해 구분을 하나, 클래스는 독자적인 자료형으로 다루는 것이 권장된다.
핵심 내장객체와 클라이언트 측 호스트 객체는 classof() 함수로 클래스의 속성을 구별할 수 있다.
하지만 평범하게 선언하는 경우 언제나 클래스의 속성은 Object 이므로 도움이 되지 않는다.
다음 3가지로 해당 객체의 클래스를 판단하여보자
instanceof
생성자는 클래스를 구별하는 대표적인 수단이나, 구별의 핵심은 프로토타입니다.
생성자 함수를 요구하여 검사하는 연산자 이나, 실제로는 객체가 어떤 프로토타입을 상속했는지 검사하고 생성짜함수를 어떤 것을 썼는지 검증하지 않는다.
위와 같은 사실 때문에 생성자 함수를 검사의 기준을 삼고 싶지 않으면 isPrototype() 을 권장한다.
하지만 이조차 완벽하지 않다. 주어진 객체와 클래스의 관계만 테스트만하고 심지어 특정객체의 클래스가 무엇인지 알수 없다.
더 심각한점, 둘 이상의 화면과 프레임을 사용하는 상황에서 각각은 서로 구분되는 실행 컨텍스트를 가지기 때문에 각각의 전역객체와 생성자함수의 집합을 가진다.
이름이 같더라도 실행 컨텍스트가 다르기 때문에 같은 생성자의 인스턴스가 아니다!!!
constructor property
위 연산자와 동일한 문제를 가지고 있고, 객체에 따라 constructor property 를 사용하지 않는 것도 존재한다.
생성자 이름 함수
생성자의 이름을 함수로 리턴하는 방법을 꾀하는 것도 방법일 수 있으나 이 조차도 함수에 이름이 없는 경우도 존재하기 때문에 좋지않다.
위 세가지로 확인하는 법은 전적으로 만족스럽지 않다.
Duck-Typing
앞서 야기된 방법들은 각각의 문제점을 가지고 있다.
위를 해결하기 위해서 나온 대안책
이 객체가 무엇인가? 의 관점에서
이 객체가 할 수 있는 일은 무엇인가의 관점을 가지는 것이다.
위와 같은 접근법은 덕 타이핑이라 불리운다.
새 한마리가 오리처럼 걷고 오리처럼 울면, 그 새는 오리다.
말인 즉슨, 프로토타입 객체를 상속받지 않더라도 그 기능을 수행한다면 해당 클래스로 취급할 수 있다는 점이다.
해당 객체가 어떤 메서드를 가지고 있는지 테스트를 하는 것이다.
구현하는 법
무간섭주의를 준수 하는 것이다.
입력 객체가 필요한 메서드를 구현한다 가정할 때, 이 입력객체가 메서드를 실제로 구현하고있는지 검사를 하지 않는다.
이 가정이 틀릴 시, 존재하지 않는 메서드를 호출한다는 에러가 나타난다.
검증을 하되, 클래스대신 적합한 이름을 가진 메서드가 구현되있는지 검사.
위 방법대로 준수하면 적절하지 않은 입력이 있을 경우 대응이 된다.
에러 메세지에 디테일함을 추구할 수 있다.
덕 타이핑을 위한 예시 함수
위 함수는 객체의 특정 이름의 함수 프로퍼티가 있는지 검증만 한다.
함수가 어떤 역할을 하는지, 인자값의 개수는, 무슨 자료형인가는 검증을 안한다.
원래 덕 타이핑이란 그런 것이라고 한다.
심도 깊은 검증을 하는 함수 대신 덕 타이핑을 사용하는 함수를 사용하면 더 유연한 api를 제공하는 것이다.
하지만 이는 사용자에게 책임을 떠넘기는 행위가 되버린다.
이너클래스에 대해선 동작을 하지 않으니 구지 하고싶다면 Object.getOwnPropertyNames() 같은 함수를 사용한다.
자바스크립트의 객체지향 기법, ES5 클래스
많기도 많고, 데이터에 대한 가공은 java 에서 주로 하고 있기때문에 구지 이곳에 이 관점을 더 이상 생각하고 싶지않다. Node.js 라면 모를까..
열거형은 제법 쓸만할 것같다.
Last updated
Was this helpful?