티스토리 뷰
이선 브라운의 러닝 자바스크립트 책을 학습하고 기억해둘 만 한 부분을 야생학습하여 정리하였습니다.
프로퍼티 나열
컨테이너의 컨텐츠를 리스트로 나열하라고 하면 일반적으로 배열을 생각하지만 자바스크립트에서 객체또한 컨테이너이고 프로퍼티 나열을 지원합니다. 주의해야할 점은 프로퍼티 나열에서 순서대로 나열된다는 보장이 없다는 점입니다.
For ... in
const SYM = Symbol();
const o = { a: 1, b: 2, c:3, [SYM]: 4}; //for...in 루프에서는 키가 심볼인 프로퍼티는 포함X
for(let prop in o){
if (!o.hasOwnProperty(prop)) continue;
console.log(`${prop}: ${o[prop]}`);
}
hasOwnProperty가 왜 중요한지는 아래에 나올 설명할 예정입니다.
Object.keys
object.keys는 객체에서 나열 가능한 문자열 프로퍼티를 배열로 반환합니다.
const SYM = Symbol();
const o = { a: 1, b: 2, c:3, [SYM]: 4}; //for...in 루프에서는 키가 심볼인 프로퍼티는 포함X
Object.keys(o).forEach(prop => console.log(`${prop}: ${o[prop]}`));
나열 가능한 프로퍼티만 가져오기 때문에 hasOwnProperty를 사용할 필요가 없습니다.
객체지향 프로그래밍
클래스와 인스턴스 생성
ES6에서는 클래스를 만드는 간편한 새 문법을 도입했습니다.
class Car {
constructor() {
}
}
인스턴스를 만들 때는 new 키워드를 사용합니다.
const car1 = new Car();
const car2 = new Car();
객체가 특정 클래스의 인스턴스인지 확인하기 위해 instanceof 연산자를 사용합니다.
클래스는 함수다
ES6에서 class 키워드를 도입하기 전까지 클래스를 만든다는 것은 곧 클래스 생성자로 사용할 함수를 만든다는 의미였습니다. class는 단축 문법일 뿐이며 자바스크립트의 클래스 자체가 바뀐 것이 아니라서 자바스크립트만의 클래스 자체를 이해하는 것이 중요합니다.
클래스는 사실 함수입니다. ES5에서는 클래스를 이렇게 만들었습니다.
function Car(make, model) {
this.make = make;
this.model = model;
this._userGears = ['P', 'N', 'R', 'D'];
this.userGear = this.userGears[0];
}
ES6에서도 똑같이 할 수 있고 결과 또한 동일합니다.
프로토타입
클래스가 인스턴스에서 사용할 수 있는 메서드라고 하면 그건 프로토타입 메서드를 뜻합니다. 예로 아까 전 예시인 Car의 인스턴스에서 사용할 수 있는 shift 메서드는 프로토타입 메서드입니다. 프로토타입 메서드는 Car.prototype.shift처럼 표기할 때가 많습니다(최근에는 프로토타입 메서드를 #으로 표기하기도 합니다. Array.prototype.forEach -> Array#forEach)
모든 함수에는 prototype이라는 특별한 프로퍼티가 있습니다. 일반적인 함수에서는 사용할 일이 없지만 객체 생성자로 동작하는 함수에서는 프로토타입이 굉장히 중요합니다. 함수의 prototype 프로퍼티가 중요해지는 시점은 new 키워드로 새 인스턴스를 만들었을 때입니다. new 키워드로 만든 새 객체는 생성자의 prototype 프로퍼티에 접근할 수 있습니다. 객체 인스턴스는 생성자의 prototype 프로퍼티를 __proto__ 프로퍼티에 저장합니다.
프로토타입에서 중요한 개념은 동적 디스패치라는 매커니즘인데 디스패치는 메서드 호출과 같은 의미입니다. 객체의 프로퍼티나 메서드에 접근하려 할 때 그런 프로퍼티나 메서드가 존재하지 않으면 자바스크립트는 객체의 프로토타입에서 해당 프로퍼티나 메서드를 찾습니다. 클래의 인스턴스는 모두 같은 프로토타입을 공유하므로 해당 클래스의 인스턴스는 모두 그 프로퍼티나 메서드에 접근 가능합니다.
인스턴스에서 메서드나 프로퍼티를 정의하면 프로토타입에 있는 동명의 것을 가리는 효과가 있습니다. 인스턴스를 먼저 체크하고 없다면 프로토타입을 체크하기 때문입니다.
정적 메서드
정적 메서드에서 this는 인스턴스가 아니라 클래스 자체에 묶입니다. 정적 메서드는 클래스 자체의 추상적인 개념이나 여러 인스턴스를 비교하거나 대상으로 하는 곳에 쓰입니다.
상속
클래스의 인스턴스는 클래스의 기능을 모두 상속하며 객체의 프로토타입에서 메서드를 찾지못하면 프로토타입의 프로토타입을 찾아 올라가기 때문에 프로토타입 체인이 만들어집니다. extends 키워드를 이용하여 상속하고 슈퍼클래스의 생성자를 호출하는 super() 클래스를 서브클래스에서 반드시 호출시켜 구현합니다.
hasOwnProperty
hasOwnProperty는 프로퍼티가 obj(프로토타입 체인의 취상위)에 정의되지 않았거나 프로토타입 체인에만 정의되었다면 false를 반환하기 때문에 프로토타입에 프로퍼티를 정의해두었다면 빼먹을 여지가 있기 때문에 안전한 코딩을 위해 사용한다.
믹스인
객체지향언어중에는 다중 상속을 지원하는 언어도 있고 다중 상속이 가지고 있는 충돌의 위험 때문에 인터페이스라는 개념을 도입하기도 합니다. 자바스크립트의 경우 절충안으로 믹스인(mixin)이라는 개념을 만들었습니다. 믹스인이난 기능을 필요한 만큼 섞어 놓은 것입니다. 타입에 관대한 언어이기 때문에 어떤 기능이라도 어떤 객체에든 추가할 수 있습니다.
class InsurancePolicy {}
function maekInsurable(o){
o.addInsurancePolicy = function(p) { this.insurancePolicy = p;}
o.getInsurancePolicy = function() { return this.insurancePolicy;}
o.isInsured = function() {return !!this.insurancePolicy;}
믹스인의 Car의 특정 인스턴스에 적용시켰습니다.
const car1 = new Car();
makeInsurable(car1);
car1.addInsurancePolicy(new InsurancePolicy());
그러나 모든 자동차에 적용하기 위해선 일일히 추가해야 하는 문제가 있습니다. 해결방안으로 클래스의 프로토타입 프로퍼티에 붙여주는 방법이 있습니다.
makeInsurable(Car.prototype);
const car1 = new Car();
car1.addInsurancePolicy(new InsurancePolicy());
'Running JS 요약' 카테고리의 다른 글
JS - 이터레이터와 제너레이터 (0) | 2021.01.20 |
---|---|
JS - 맵과 셋 / 예외와 에러 처리 (0) | 2021.01.18 |
JS - 배열 (0) | 2021.01.06 |
JS - 스코프 (0) | 2021.01.05 |
JS - 함수 (0) | 2021.01.04 |