본문 바로가기

TIL

코어자바스크립트 chapter 6

👉프로토타입이란?

어떤 객체를 원형으로 삼고 이를 복제(참조)함으로써 상속과 비슷한 효과를 얻는다 

(객체를 상속하기 위해 사용되는 방식. 객체이며 해당 객체를 바라봄으로써 상속받을 객체의 메서드 및 속성에 접근가능)

 

https://developer.mozilla.org/ko/docs/Learn/JavaScript/Objects/Object_prototypes

자바스크립트에서 프로토타입이란

객체를 생성할 때 메서드와 프로퍼티를 상속받기 위해 참조하는 객체라고 할 수 있다.

 

👉Constructor, prototype, instance

 

var instance = new Constructor();

 

어떤 생성자 함수를 new 연산자와 함께 호출하면 

Constructor에서 정의된 내용을 바탕으로 새로운 인스턴스가 생성됨 

이때 instance에 __proto__라는 프로퍼티 자동으로 부여

이 프로퍼티는 Constructor의 prototype이라는 프로퍼티를 참조

 

 

👉prototype과 __proto__ 의 차이

prototype 객체 내부에 인스턴스가 사용할 메서드 저장

인스턴스에서 __proto__를 통해 메서드들에 접근

__proto__말고 Object.getPrototypeOf() / Object.create() 로 접근 권장 

 

 

👉prototype에 메서드 지정하는 방법 

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

Person.prototype.getName = function () {
    return this._name;
}

var person = new Person('json Lee');
person.__proto__.getName(); //undefined

 

undefined가 나오는 이유는 person.__proto__ 객체의 name을 호출하는 것이기 때문

 

this를 인스턴스로 하는 방법 : __proto__없이 인스턴스에서 메서드 쓰기

__proto__를 생략하고 앞의 인스턴스로 부르기 

person.getName(); // json Lee

 

👉프로토타입의 개념 

자바스크립트는 함수에 객체인 prototype 프로퍼티 생성

생성자 함수로 사용할 경우 인스턴스에 숨겨진 메서드 __proto__가 자동 생성

__proto__는 생략 가능

그러므로 인스턴스에서 자신의 것처럼 프로토타입의 메서드 프로퍼티에 접근 가능


👉new 연산자와 함께 생성자 함수 호출 할 때의 과정 

1. 인스턴스 생성과 this 바인딩 

2. 인스턴스 초기화

3. 암묵적으로 인스턴스 바인딩된 this 반환

 

👉constructor와 non-constructor의 구분

👉constructor프로퍼티란? 

모든 프로토타입이 가지고 있는 프로퍼티. 

prototype프로퍼티로 자신을 참조하고 있는 생성자함수를 가리킴

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

const me = new Person('Lee');

//me 객체의 생성자함수는 Person
console.log(me.constructor === Person); //true;

 

 

constructor : 함수선언문, 함수표현식, 클래스

non-constructor: 메서드, 화살표함수  ---> 생성자함수로서 호출할 수 없다.

constructor 속성을 가지고 있으면 new 연산자와 함께 생성자함수로서 호출할 수 있는데, 

만일 생성자함수로서 호출하지 않는 함수는 this가 전역으로 바인딩되며 

클래스는 호출할 수 없으므로 reference Error가 난다. 

prototype 프로퍼티도 non-contsructor에는 존재하지 않는다.

 

👉new.target이란? 

생성자함수로서 호출되었는지 여부를 알 수 있는 방식

 

👉enumerable

object의 프로퍼티는 세가지 요인에 의해 구분된다. 

- enumerable한가?

- string인가 symbol인가 

 - property를 가지고 있나 혹은 프로로타입의 체인에 의해 상속되었는가?

 

enumberable 프로퍼티는 enumerable 플래그가 true로 설정된 프로퍼티다.

대부분의 iteration (for...in루프 혹은 Object.keys와같은)기능은 enumberable keys만 방문한다.

 

프로퍼티의 소유는 프로퍼티가 object에 직접 속하였는지, prototype chain에 속하였는지다. 

모든 프로퍼티는 닷 노테이션 혹은 []브라켓 노테이션을 통해 접근 가능하다. 

 

Object.defineProperty(obj, 'nonEnumerable', {
  value: 'This will not be enumerated',
  enumerable: false
});

obj.enumerable = 'This will be enumerated';

// for...in 루프를 사용하여 열거
for (let key in obj) {
  console.log(key); // "enumerable"만 출력됨
}

console.log(Object.keys(obj)); // ["enumerable"]
console.log(obj.nonEnumerable); // "This will not be enumerated"

 

👉prototype에 의해 상속되지 않는 메서드 

isArray(), assign(), of(), length, from, arguments

이들은 생성자함수에서 직접 접근해야 한다.

 

 

👉constructor 프로퍼티

생성자 함수의 프로퍼티 prototype의 내부에 constructor 프로퍼티 존재

생성자 함수 원본을 참조

 

var arr = [1, 2]; 
Array.prototype.constructor === Array //true
arr.__proto__.constructor === Array //true
arr.constructor === Array //true

var arr2 = new arr.constructor(3, 4);
console.log(arr2); // [3, 4]

 

👉constructor 접근방법 

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

var p1 = new Person('사람1');
var p1Proto = Object.getPrototypeOf(p1);
var p2 = new Person.prototype.constructor('사람2');
var p3 = new p1Proto.constructor('사람3');
var p4 = new p1.__proto__.constructor('사람4');
var p5 = new p1.constructor('사람5');

[p1, p2, p3, p4, p5].forEach(function (p) {
    console.log(p, p instanceof Person);
});

 

 

👉메서드 오버라이드

인스턴스가 constructor의 프로퍼티나 메서드와 동일한 이름을 가지고 있다면?

오버라이드 된다. 

자바스크립트 엔진이 가장 가까운 자신의 프로퍼티를 검색하고 없으면 __proto__를 검색하기 때문

메서드 오버라이딩은 얹는 개념이기 때문에 덮어씌워지지 않는다. 그러므로 프로토타입의 메서드에 접근할수 있다.

 

var Person = function (name) {
	this.name = name;
}
Person.prototype.getName = function () {
    return this.name;
}

var iu = new Person('지금');
iu.getName = function () {
    return '바로 '+ this.name;
}
console.log(iu.getName()); //바로 지금

console.log(iu.__proto__.getName()); //undefined

console.log(iu.__proto__.getName.call(iu)); //지금

 

 

 



👉프로토 타입 체이닝

 

 

var arr = [1, 2];
Array.prototype.toString.call(arr) // 1, 2
Object.prototype.toString.call(arr) // [object Array]
arr.toString();

arr.toString = function () {
  return this.join('_');
}
arr.toString();

 

Array의 prototype은 Object

 

👉객체 전용 메서드의 예외사항

어떤 생성자 함수이든 prototype은 반드시 객체이므로 Object.prototype이 언제나 프로토타입의 최상단 

객체에서만 사용할 메서드는 프로토타입 객체안에 정의하면 안된다. 

다른 데이터 타입도 사용할 수 있게 되기 때문

그러므로 Object에 객체만 활용할 수 있는 메서드를 할당

 

Object.prototype에 있는 메서드들은 어떤 데이터에서도 사용할 수 있는 범용적인 메서드

toString, hasOwnProperty, valueOf, isPrototypeOf등

 

 

👉Object.prototype에 접근할 수 없게 객체 생성하는 방법

Object.create(null)

 

 

👉다중 프로토타입 체인

__proto__ 를 연결하면 무한대로 체인 관계를 이어나갈 수 있다.

__proto__가 가리키는 대상이 상위 생성자함수의 인스턴스를 바라보게끔 해주면 된다.

var Grade = function () {
    var args = Array.prototype.slice.call(arguments);
    for (var i = 0 ; i < args.length; i++ ) {
        this[i] = args[i];
    }
    this.length = args.length;
};

var g = new Grade(100, 80);

 

Grade.prototype = [] 으로 할당하면

Grade의 prototype은 Array가 되며 Array의 메서드를 prototype상속을 통해 __proto__를 생략후 

메서드로 사용할 수 있게 된다. 

그러므로 유사배열객체를 return하고 있는 Grade생성자함수를 배열의 메서드를 사용할 수 있도록 만들었다.

'TIL' 카테고리의 다른 글

웹 서비스를 제공하는 방식  (0) 2024.06.19
결합도와 응집도  (0) 2024.06.18
코어자바스크립트 chapter 5  (0) 2024.05.28
코어자바스크립트 chapter 4 예상 질문 정리  (0) 2024.05.27
코어자바스크립트 chapter 3  (0) 2024.05.26