chapter9. 객체와 객체지향 프로그래밍

9.1 프로퍼티 나열

1) 배열은 값을 가지며 각 값에는 숫자형 인덱스가 있습니다.
객체는 프로퍼티를 가지며 각 프로퍼티에는 문자열이나 심볼 인덱스가 있습니다
2) 배열에는 순서가 있습니다. 반면 객체는 그런 순서가 보장되지 않습니다.

9.1.1 for…in

  • for…in : 객체 프로퍼티를 나열할 떄
1
2
3
4
5
6
7
8
9
10
11
12
const SYM = Symbol();
const o ={a:1,b:2,c:3,[SYM]:4};
for(let prop in o){
if(!o.hasOwnProperty(prop)) continue;
console.log(`${prop}:${o[prop]}`)
}

/*
a:1
b:2
c:3
*/
hasOwnProperty : for...in에 나타날 위험을 제거하기 위해 사용
for...in 루프에는 키가 심볼인 프로퍼티는 포함 안됌

9.1.2 Object.keys

객체에서 나열 가능한 문자열 프로퍼티를 배열로 반환

1
2
3
4
5
6
7
8
9
10
// 9.1.2 Object.keys
const SYM = Symbol();
const o ={a:1,b:2,c:3,[SYM]:4};
Object.keys(o).forEach(prop => console.log (`${prop} :${o[prop]}`));

/*
a:1
b:2
c:3
*/
hasOwnProperty를 체크할 필요가 없다.
객체의 프로퍼티 키를 배열로 가져와야 할때 Object.keys가 편리하다.

9.2 객체지향 프로그래밍

OOP) 객체 : 데이터와 기능을 논리적으로 묶은 것

  • 클래스 : 자동차처럼 추상적이고 범용적인 것
  • 인스턴스 : 특정 자동차처럼 구체적이고 한정적인 것
  • 메서드 : 기능
  • 클래스 메서드 : 클래스지만 특정 인스턴스에 묶이지 않는 기능
  • 생성자 : 인스턴스를 처음 만들 떄 생성자가 실행됨, 객체 인스턴스를 초기화함

클래스 : 운송수단
서브 클래스 : 자동차, 보트, 비행기..
보트 서브 클래스 : 요트, 카누,모터보트…

9.2.1 클래스와 인스턴스 생성

ES6애서 클래스를 만드는 간편한 새 문법을 도입함

클래스만들기
1
2
3
4
5
class Car{
constructor(){

}
}
새 클래스 Car을 만듬, 아직 인스턴스(특정 자동차)는 안만들어짐
인스턴스만들기
1
2
const car1 = new Car();
const car2 = new Car();
인스턴스를 만들 떈 new 키워드를 사용한다
instanceof
1
2
3
//instanceof
car1 instanceof Car //true
car1 instanceof Bus //false
instanceof : 객체가 클래스인지, 인스턴스인지 확인
car1은 Car의 인스턴스이지만, Bus의 인스턴스는 아니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//제조사, 모델, 변속 기능 추가
class Car{
constructor(make, model){
this.make = make;
this.model = model;
this.userGears = ['P','N','R','D'];
this.userGear = this.userGears[0];
}
shift(gear){
if(this.userGears.indexOf(gear)<0)
throw new Error('invalid gear :' `${gear}`);
this.userGear = gear
}
}

//실제 사용
const car1 = new Car('Thsla','Model S');
const car2 = new Car('Mazda','3i');
car1.shift('D');
car2.shift('R');

car1.userGear //"R"
this : 메서드를 호출한 인스턴스를 가리키는 목적 
userGears :  사용할 수 있는 기어 목록
gear :  현재 기어 사용할 수 있는 첫번째 기어로 초기화
shift : 메서드(기어변속)

* 실수로 기어 프로퍼티를 고치지 않도록 어느 정도 막을 수 있다.
_ : 외부에서 접근하면 안돼는 프로퍼티 이름 앞에 붙이는 가짜 접근 제한 ex)_userGears

9.2.2 클래스는 함수다.

ES6에서 class 키워드를 도입하기 전까지,
클래스를 만드는 것은 곧 클래스 생성자로 사용될 함수를 만든다는 의미
but, class는 단축 문법일 뿐이고 자바스크립트의 클래스가 바뀐 것은 아님

es5
1
2
3
4
5
6
function Car(make,model){
this.make = make;
this.model = model;
this.userGears = ['P','N','R','D'];
this.userGear = this.userGears[0];
}
es6
1
2
3
4
class Es6Car {} //생성자는 의도적으로 생략
function Es5Car {}
> typeof Es6Car //'function'
> typeof Es5Car //'function'

9.2.3 프로토타입

프로토타입 메서드: 클래스의 인스턴스에서 사용할 수 있는 메서드
ex) Car.prototype.shift :
Car 클래스의 인스턴스에서 사용할 수 있는 shift 메서드는 프로토타입 메서드임

  • 최근엔 메서드를 ‘#’로 표기하기도함 ex)Car#shift
  • 클래스는 대문자로 시작하는게 관용적임
  • 함수의 prototype 프로퍼티가 중요한 시점은 new 키워드로 새 인스턴스를 만들때
  • new 키워드로 만든 새 객체는 생성자 prototype 프로퍼티에 접근가능
  • proto‘(밑줄 2개) 프로퍼티에 저장()
  • 동적 디스패치 : 메서드 호출
prototype
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//9.2.3 프로토타입
const Car = (function(){
const carProps = new WeakMap();

class Car{
constructor(make,model){
this.make = make;
this.model = model;
this._userGears = ['P','N','R','D'];
carProps.set(this,{userGear:this._userGears[0]});
}
get userGear(){return carProps.get(this).userGear;}
set userGear(value){
if(this._userGears.indexOf(value)<0)
throw new Error(`${value}`);
carProps.get(this).userGear = value;
}
shift(gear){this.userGear = gear;}
}
return Car;
})();


const car1 = new Car();
const car2 = new Car();
car1.shift === Car.prototype.shift; //true;
car1.shift('D');
car1.shift('d');//error;
car1.userGear; // 'D';
car1.shift === car2.shift; //true;

car1.shift = function(gear) {this.userGear = gear.toUpperCase();}
car1.shift === Car.prototype.shift; //false

9.2.4 정적 메서드

정적 메서드 : 클래스 메서드

  • 특정 인스턴스에 적용되지 않음
  • this는 인스턴스가 아니라 클래스 자체에 묶임
  • 클래스와 관련되지만 인스턴스와 관련없는 범용적 작업에 사용
    ex) 자동차 식별 번호 (VIN) 붙이기
  • 여러 인스턴스를 대상으로 하는 작업에도 사용
정적메서드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//areSimilar : 두 자동차의 제조사와 모델이 같으면 true 반환 메서드
//areSame : 두 자동차의 VIN이 같으면 true반환 메서드
class Car{
static getNextVin(){
return Car.nextVin++; //this.nextVin++이라고 써도 되지만,
// Car을 앞에 쓰면 정적 메서드라는 걸 상기
}
constructor(make,model){
this.make = make;
this.model = model;
this.vin = Car.getNextVin();
}
static areSimilar(car1,car2){
return car1.make == car2.make && car1.model == car2.model;
}
static areSame(car1,car2){
return car1.vin === car2.vin;
}
}
Car.nextVin = 0; //초기값

const car1 = new Car("Tesla","S");
const car2 = new Car("Mazda","3");
const car3 = new Car("Mazda","3");

car1.vin; //0
car2.vin; //1
car3.vin; //2

Car.areSimilar(car1,car2);//false
Car.areSimilar(car2,car3);//true
Car.areSame(car2,car3);//false
Car.areSame(car2,car2);//true

9.2.5 상속

클래스 인스턴스는 클래스의 기능을 모두 상속한다.

  • 프로토타입 체인 :
    조건에 맞는 프로토타입을 찾을 때 까지 체인을 계속 거슬러감
    프로토타입을 찾지 못하면 에러를 일으킴
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//프로토타입 체인
/*
deployAirbags
*/
class Vehicle {
constructor(){
this.passengers = [];
console.log("Vehicle created");
}
addPassenger(p){
this.passengers.push(p);
}
}

class Car extends Vehicle{
constructor(){
super();
console.log("Car created");
}
deployAirbags(){
console.log("BWOOSH");
}
}

const v = new Vehicle();
v.addPassenger("Frank");
v.addPassenger("Judy");
v.passengers; // ["Frank","Judy"];

const c = new Car();
c.addPassenger("Alice");
c.addPassenger("Cameron");
c.passengers; //["Alice","Cameron"]

v.deployAirbags(); //error
c.deployAirbags(); //console.log("BWOOSH");
  • extends : Car를 Vehicle의 서브 클래스로 만듬
  • super() : 슈퍼클래스의 생성자 호출, 서브클래스에서는 이 함수를 반드시 호출
c 에서는 deployAirbags 호출 가능, v 에서는 error
서브클래스는 슈퍼클래스의 모든 메서드에 접근 가능 / 반대는 불가

9.2.6 다형성

다형성 : 여러 슈퍼클러스의 맴버인 인스턴스
instanceOf 연산자: 객체가 클래스의 인스턴스인지 확인

다형성
1
2
3
4
5
6
7
8
9
//다형성
// Vehicle : 슈퍼클래스
// Motorcycle 와 Car는 Vehicle의 서브클래스임
class Motorcycle extends Vehicle{};
const c = new Car();
const m = new Motorcycle();
c instanceof Car; //true
c instanceof Vehicle; //true
m instanceof Car //false
  • 자바스크립트의 모든 객체는 루트 클래스인 Object의 인스턴스이다

9.2.7 객체 프로퍼티 나열 다시 보기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//
class Super{
constructor(){
this.name = 'Super';
this.isSuper = true;
}
}
//유효하지만 권장x
Super.prototype.sneaky = 'not recommended';

class Sub extends Super{
constructor(){
super();//서브클래스는 써줘야함
this.name = 'Sub';
this.isSub = true;
}
}

const obj = new Sub();
for(let p in obj){
console.log(`${p} : ${obj[p]}`+ (obj.hasOwnProperty(p)? '': '(inherited)'));
}

/*
name : Sub
isSuper : true
isSub : true
sneaky : not recommended(inherited)
*/

9.2.8 문자열 표현

toString : 객채의 기본적인 문자열 표현을 제공

9.3 다중 상속, 믹스인, 인터페이스

다중 상속 : 클래스가 슈퍼 클래스 두 개를 가지는 기능, 충돌 위험 존재
인터페이스 : 다중 상속을 지원하지 않는 언어의 경우 인터페이스를 도입
믹스인 : 기능을 필요한 만큼 섞은 것
Symbol() : 심볼은 고유하므로, 다른 슈퍼클래스의 기능과 충돌할 가능성이 없다.

Comentarios

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×