본문 바로가기

코드스테이츠(Pre)

자바스크립트_객체지향 프로그래밍(OOP)

자바스크립트는 클래스 기반의 언어들과 달리 프로토 타입 기반의 객체 지향 프로그래밍언어(ES6에서는 클래스도 추가)

 

extend 와 프로토타입 체인의 구별

extend의 경우 실제 object의 프로퍼티에 추가

var person = {
    firstname : 'Default',
    lastname : 'Default',
    getFullName : function() {
    	return this.firstname + ' ' + this.lastname;
     }
}

var john = {
    firstname : 'John',
    lastname : 'Doe'
}

john.__proto__ = person; // john 객체에서 프로퍼티 메소트 찾은 후 없으면 proto 탐색

for(var prop in john){
	if(john.hasOwnProperty(prop)){ // if문이 없다면? getFullName 메소드 출력
    	console.log(prop + ': ' + john[prop])
    }
}
// firstname : 'John', lastname: 'Doe'

var jane = {
	address: '111 Main St.';
        getFormalFullName: function(){
    		return this.lastname + ', ' + this.firstname;
    }
}

var jin = {
	getFirstName: function(){
    	return firstname;
    }
}

_.extend(john, jane , jim)
console.log(john)
// {firstname, lastname, address, getFormalFullName, getFirstName}
// 프로토타입과의 차이 : 실제 john object의 property 로 추가

 

생성자 함수와 'new' keyword

  -> prototype 생성

function Person(firstname, lastname) {
    console.log(this); // Person {}
    this.firstname = firstname;
    this.lastname = lastname;
    console.log('function is invoked');
}

var john = new Person('John', 'Doe'); 
// operator 'new' -> var a = {}; empty object is created
console.log(john);

1.{} 빈 객체 생성 
2.() 함수 실행 
3. Person 안의 this가 new 키워드로 생성된 빈 객체를 가르킴
4. firstname, lastname 추가
5. 생성된 객체 리턴

new 키워드를 빼먹을경우 객체가 아니라 undefined로 리턴 

new를 빼먹지 않도록 생성자 함수의 첫번째 글자를 대문자로!

 

Prototype vs prototype 프로퍼티

the prototype property on a function is not the prototype of the function. 

(함수의 프로토타입 프로퍼티는 함수의 프로토타입은 아니다)

function Person(name) {
	this.name = name;
}

var foo = new Person('Lee');

console.log(Person);	// prototype 프로퍼티가 있다.
console.log(foo);		// prototype 프로퍼티가 없다.

- Prototype

함수를 포함한 모든 객체가 가지고 있음

객체의 입장에서 자신의 부모 역할을 하는 프로토타입 객체를 가르킨다(함수의 경우 Function.prototype)

- prototype 프로퍼티

함수 객체만 가지고 있음

함수 객체가 생성자로 사용될 때 이 함수를 통해 생성될 객체의 부모 역할을 하는 객체(프로토타입 객체)를 가르킨다.

생성자 함수를 통해서 객체가 생성될때 prototype property가 사용된다

Person.prototype.getFullName = function() {
	return this.firstname + ' ' + this.lastname;
}
// new Person() 으로 생성된 객체들은 모두 getFullName() 프로퍼티를 갖는다.

console.log(john.getFullName());
// John Doe

Person 생성자 함수에 메소드를 추가할 경우, 모든 객체에 추가 되기때문에 메모리가 낭비된다.

 


프로토타입은 크게 두 가지 의미로 해석
프로토타입 객체를 참조하는 prototype 속성과 -> 프로토타입 프로퍼티
객체 멤버인 proto 속성이 참조하는 숨은 링크가 있습니다. (__proto__)


function Person(){}
// 프로토타입 프로퍼티와 프로토타입의 구분
// Person 함수의 프토토타입 프로퍼티는 함수이름을 가진 Prototype 객체 참조(원형) 

var jun = new Person();  
var jisoo = new Person();
// new 로 생성된 모든 객체의 원형은 Prototype
// __proto__ 프로퍼티가 원형 Prototype 객체를 참조하는 링크 역할

Person.prototype.getType = function (){  
    return "인간"; 
};
// 프로토타입 프로퍼티 이용해서 getType 메소드 추가 (추가, 수정, 삭제시는 프로토타입 원형 이용)
// 전에 생성된 객체는 이후에 프로토타입에 추가된 메소드 이용 가능


console.log(jun.getType());   // 인간  
console.log(jisoo.getType());  // 인간 
// 읽을때는 함수 안의 prototype 프로퍼티 혹은 객체의 이름으로 접근

// 생성된 객체의 프로퍼티를 수정할 경우 프로토타입의 프로퍼티를 수정하는 것이아니라
// 객체의 프로퍼티를 추가하는것
jun.getType = function (){  
    return "사람"; 
};
// jun 객체의 getType을 호출하면 프로토타입의 getType을 호출한것이 아니라 
// jun 객체의 추가된 getType 프로퍼티를 호출한것
console.log(jun.getType());   // 사람  
console.log(jisoo.getType());  // 인간

jisoo.age = 25;

console.log(jun.age);   // undefined  
console.log(jisoo.age);  // 25  

// 프로토타입의 프로퍼티 이용해 리턴값 수정
Person.prototype.getType = function (){  
    return "사람"; 
};

console.log(jisoo.getType());  // 사람

 

Object.create

var person =  {
    firstname: 'Default',
    lastname: 'Default',
    greet: function() {
    	return 'Hi ' + this.firstname;
    }
}

// 빈 객체와 Object.create가 가리키는 prototype의 프로퍼티를 가져온다
var john = Object.create(person);
john.firstname = 'John';
john.lastname = 'Doe';
console.log(john);

 

Class

class InformalPerson extends Person { 
				// prototype 설정

	constructor(firstname, lastname) {
    		super(firstname, lastname);
    }
    
    greet(){
    	return 'Yo' + firstname;
        }
 }