Search
Duplicate
🖼️

Object

: JavaScript 객체는 키-값 쌍을 가질 수 있게 해주는 데이터 구조
: 고유한 키를 가질 수 있으며 각 키는 모든 JavaScript 데이터 유형이 될 수 있는 값에 매핑
: 실제 개체와 비교할 때 펜은 색상, 디자인, 재질 등과 같은 여러 속성을 가진 개체로, Object는 특성을 정의하는 속성을 가질 수 있음

Built-in Objects

Numbers
Math
Date
String
Error
Function
Boolean

Prototype

: JavaScript는 흔히 프로토타입 기반 언어라 불리는데, 모든 객체들이 메소드와 속성들을 상속 받기 위한 템플릿으로써 프로토타입 객체를 가짐
: 프로토타입 객체 또한 상위 프로토타입 객체로부터 메소드와 속성을 상속받을 수 있고 그 상위도 마찬가지, 이를 프로토타입 체인이라고 부름
: 상세하게는 상속되는 속성과 메소드는 각 객체가 아닌 객체의 생성자의 prototype이라는 속성에 정의되어 있음
프로토타입 객체 이해하기
function Person(first, last, age, gender, interests) { // 속성과 메소드 정의 this.first = first; this.last = last; //... } var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);
JavaScript
복사
: 위와 같이 객체를 정의하고 해당 객체를 바탕으로 인스턴스를 생성한 후, 콘솔이나 런타임 코드 환경에서 person1.을 입력하면 해당 객체의 멤버 이름을 자동으로 팝업
: 이때 Person()에 정의된 멤버들 외에도watch, valueOf처럼 Person()의 프로토타입 객체인 Object에 정의된 다른 멤버또한 존재함을 알 수 있음
프로토타입 속성
: 상속 받은 멤버들이 정의된 곳
: 상속받는 멤버들은 prototype 속성에 정의되어 있음, 즉 Object.가 아닌 Object.prototype.에 들어있음, 상속생성자 솏
create() 다시보기
: 새 인스턴스를 생성하기 위한 메소드인 Object.create()를 사용하면 주어진 객체를 프로토타입 객체로 삼아 새로운 객체를 생성
var person2 = Object.create(person1); person2.__proto__ //person1
JavaScript
복사
생성자 속성
: 모든 생성자 함수는 constructor 속성을 지닌 객체를 프로토타입 객체로 보유하고 있음 이는 원본 생성자 함수 자신을 가리키고 있는데
: 각 생성된 인스턴스에서 constructor 속성에 접근할 수 있게 해줌
person1.constructor person2.constructor // Person() constructor 반환, 즉 다음과 같은 용법이 가능 var person3 = new person1.constructor('Karen', 'Stephenson', 26, 'female', ['playing drums', 'mountain climbing']);
JavaScript
복사

상속과 프로토타입

: 상속 관점에서 자바스크립트의 유일한 생성자는 객체뿐, 각각의 객체는 [[Prototype]]이라는 은닉 속성을 가지는데, 자신의 프로토타입이 되는 다른 객체를 가리킴
: 그 객체의 프로토타입 또한 해당 속성을 가지고 있고 이는 결국 반복되다 null을 속성으로 가지는 오브젝트에서 끝나며 이를 프로토타입 체인의 종점이라고 함
프로토타입 체인을 사용한 상속
속성 상속
: 자바스크립트 객체는 속성을 저장하는 동적인 “가방”과 프로토타입 객체에 대한 링크를 가짐
// o라는 객체가 있고, 속성 'a' 와 'b'를 갖고 있다고 하자. let f = function () { this.a = 1; this.b = 2; } let o = new f(); // {a: 1, b: 2} // f 함수의 prototype 속성 값들을 추가 하자. f.prototype.b = 3; f.prototype.c = 4; // f.prototype = {b: 3, c: 4}; 라고 하지 마라, 해당 코드는 prototype chain 을 망가뜨린다. // o.[[Prototype]]은 속성 'b'와 'c'를 가지고 있다. // o.[[Prototype]].[[Prototype]] 은 Object.prototype 이다. // 마지막으로 o.[[Prototype]].[[Prototype]].[[Prototype]]은 null이다. // null은 프로토타입의 종단을 말하며 정의에 의해서 추가 [[Prototype]]은 없다. // {a: 1, b: 2} ---> {b: 3, c: 4} ---> Object.prototype ---> null console.log(o.a); // 1 // o는 'a'라는 속성을 가지는가? 그렇다. 속성의 값은 1이다. console.log(o.b); // 2 // o는 'b'라는 속성을 가지는가? 그렇다. 속성의 값은 2이다. // 프로토타입 역시 'b'라는 속성을 가지지만 이 값은 쓰이지 않는다. 이것을 "속성의 가려짐(property shadowing)" 이라고 부른다. console.log(o.c); // 4 // o는 'c'라는 속성을 가지는가? 아니다. 프로토타입을 확인해보자. // o.[[Prototype]]은 'c'라는 속성을 가지는가? 가지고 값은 4이다. console.log(o.d); // undefined // o는 'd'라는 속성을 가지는가? 아니다. 프로토타입을 확인해보자. // o.[[Prototype]]은 'd'라는 속성을 가지는가? 아니다. 다시 프로토타입을 확인해보자. // o.[[Prototype]].[[Prototype]]은 null이다. 찾는 것을 그만두자. // 속성이 발견되지 않았기 때문에 undefined를 반환한다.
JavaScript
복사
: 즉 상위 프로토타입으로 체이닝되어 접근 후 속성값을 가져옴, 객체의 속성에 값을 지정하면 자기만의 속성이 생김
메소드 상속
: 자바 스크립트에 메소드라는 건 없음, 하지만 자바스크립트는 객체의 속성으로 함수를 지정할 수 있고 속성값을 사용하듯 사용이 가능
: 속성 값으로 지정한 함수의 상속 역시 위에서 본 속성의 상속과 동일, 상속된 함수가 실행될 때, this라는 변수는 상속된 오브젝트를 가리킴
var o = { a: 2, m: function(b){ return this.a + 1; } }; console.log(o.m()); // 3 // o.m을 호출하면 'this' 는 o를 가리킨다. var p = Object.create(o); // p 는 프로토타입을 o로 가지는 오브젝트이다. p.a = 12; // p 에 'a'라는 새로운 속성을 만들었다. console.log(p.m()); // 13 // p.m이 호출 될 때 'this' 는 'p'를 가리킨다. // 따라서 o의 함수 m을 상속 받으며, // 'this.a'는 p.a를 나타내며 p의 개인 속성 'a'가 된다.
JavaScript
복사
객체를 생성하는 여러 방법과 프로토타입 체이닝 결과
문법 생성자로 객체 생성
var o = {a: 1}; // o 객체는 프로토타입으로 Object.prototype 을 가진다. // 이로 인해 o.hasOwnProperty('a') 같은 코드를 사용할 수 있다. // hasOwnProperty 라는 속성은 Object.prototype 의 속성이다. // Object.prototype 의 프로토타입은 null 이다. // o ---> Object.prototype ---> null var a = ["yo", "whadup", "?"]; // Array.prototype을 상속받은 배열도 마찬가지다. // (이번에는 indexOf, forEach 등의 메소드를 가진다) // 프로토타입 체인은 다음과 같다. // a ---> Array.prototype ---> Object.prototype ---> null function f(){ return 2; } // 함수는 Function.prototype 을 상속받는다. // (이 프로토타입은 call, bind 같은 메소드를 가진다) // f ---> Function.prototype ---> Object.prototype ---> null
JavaScript
복사
생성자를 이용
function Graph() { this.vertexes = []; this.edges = []; } Graph.prototype = { addVertex: function(v){ this.vertexes.push(v); } }; var g = new Graph(); // g 'vertexes' 와 'edges'를 속성으로 가지는 객체이다. // 생성시 g.[[Prototype]]은 Graph.prototype의 값과 같은 값을 가진다.
JavaScript
복사
Object.create 이용
var a = {a: 1}; // a ---> Object.prototype ---> null var b = Object.create(a); // b ---> a ---> Object.prototype ---> null console.log(b.a); // 1 (상속됨) var c = Object.create(b); // c ---> b ---> a ---> Object.prototype ---> null var d = Object.create(null); // d ---> null console.log(d.hasOwnProperty); // undefined이다. 왜냐하면 d는 Object.prototype을 상속받지 않기 때문이다.
JavaScript
복사
class 키워드 이용
'use strict'; class Polygon { constructor(height, width) { this.height = height; this.width = width; } } class Square extends Polygon { constructor(sideLength) { super(sideLength, sideLength); } get area() { return this.height * this.width; } set sideLength(newLength) { this.height = newLength; this.width = newLength; } } var square = new Square(2);
JavaScript
복사
프로토타입 상속의 종류
위임형 상속
: 위임형 상속에서 프로토타입 객체는 다른 객체의 기반이 됨, 위임 프로토타입을 받을 경우, 새 객체는 해당 프로토타입에 대한 참조를 가지고 있음
: 새 객체의 속성에 접근할 때, 해당 객체가 직접적으로 속성을 소유하고 있는지 먼저 체크한다. 없다면 다음 순서로 [[Prototype]]을 체크
: 이 과정은 프로토타입 체인을 따라서 모든 객체의 프로토타입 체인의 최상위에 있는 객체인 Object.prototype에 도달할 때 까지 반복
class Greeter { constructor (name) { this.name = name || 'John Doe'; } hello () { return `Hello, my name is ${ this.name }`; } } const george = new Greeter('George'); const msg = george.hello(); console.log(msg); // Hello, my name is George
JavaScript
복사
: 객체나 배열의 상태를 변경하게 되면 같은 프로토타입을 공유하는 모든 객체의 상태가 변경, 상태 변경이 전파되는 것을 막으려면 각 객체마다 상태 값의 복사본 필요
연결형 상속
: 연결형 상속은 한 객체의 속성을 다른 객체에 모두 복사함으로써 상속을 구현, 이 상속법은 Javascript 객체의 동적 확장성을 이용한 방법
: 객체 복사는 속성의 초기값을 저장하기 위한 좋은 방법, 이 방식은 Object.assign()을 통해 구현하는 것이 보통
const proto = { hello: function hello() { return `Hello, my name is ${ this.name }`; } }; const george = Object.assign({}, proto, {name: 'George'}); const msg = george.hello(); console.log(msg); // Hello, my name is George
JavaScript
복사
: 연결형 상속은 매우 좋은 방법으로 클로져와 같이 사용한다면 훨씬 효과적인 상속 방식
함수형 상속
: 이 방법은 새 속성들을 연결형 상속으로 쌓되 상속 기능을 Factory 함수로 만들어 사용하는 방식
// import Events from 'eventemitter3'; const rawMixin = function () { const attrs = {}; return Object.assign(this, { set (name, value) { attrs[name] = value; this.emit('change', { prop: name, value: value }); }, get (name) { return attrs[name]; } }, Events.prototype); }; const mixinModel = (target) => rawMixin.call(target); const george = { name: 'george' }; const model = mixinModel(george); model.on('change', data => console.log(data)); model.set('name', 'Sam'); /* { prop: 'name', value: 'Sam' } */
JavaScript
복사