JS에서 함수는 일급 객체: 객체랑 똑같은 거야 => 덕분에 함수형 프로그래밍 가능
1. 값으로 취급 가능,
2. 어디든지 리터럴로 정의 가능,
3. 함수의 매개변수로 전달 가능,
4. 함수의 반환값으로 사용 가능
__proto__
: 모든 객체가 갖는 접근자 프로퍼티. [Prototype] 내부 슬롯에 접근할 때 씀. hasOwnProperty 에는 안 걸림. 상속 받은거라.자바스크립트는 프로토타입 기반 언어. 클래스가 있긴 한데, 그거 프로토타입임 사실.
객체의 프로퍼티나 메서드를 다른 객체가 물려받아, 그대로 제것인양 사용하는 특성. -> 코드 재사용!
1. 그냥 쌩 생성자 함수로 만들면... 새로운 인스턴스마다 새로운 메서드를 메모리 공간에 할당하는 꼴...
즉, 메모리 낭비 + 퍼포먼스 저하
function Calculator(){
this.add = (x, y) => {
return x + y;
}
};
const cal1 = new Calculator();
const cal2 = new Calculator();
function Calculator(){};
Calculator.prototype.add = (x, y) => x + y;
const cal1 = new Calculator();
const cal2 = new Calculator();
객체간 상속을 구현해주는 멋진 녀석..!
모든 객체는 만들어질때, 프로토타입이 결정 (최상위 프로토타입 Object.prototype) 되고 이는 Prototype 이라는 내부슬롯에 저장
__proto__
는 객체가, 즉 인스턴스가. prototype
은 생성자 함수가.__proto__
: 객체가 프로토타입에 접근. 게터와 세터 함수가 있어서, 값에 접근, 할당 가능. -> 비표준이므로, 권장 ㄴㄴcal1.__proto__ === Calculator.prototype; // true
cal1.__proto__ = null; // 할당
Object.getPrototypeOf(cal2) === Calculator.prototype; // true
Object.setPrototypeOf(cal2, Calculator.prototype); // 할당
const calProto = Calculator.prototype;
calProto.constructor === Calculator;
Calculator.prototype === calProto;
Object.getPrototypeOf(cal2) === calProto;
프로토타입은 생성자 함수랑 쌍으로 존재. 둘이 동시에 태어남. 런타임 전에 만들어지고, 바인딩 됨.
console.log(Calculator.prototype);
function Calculator(name){
this.name = name;
};
빌트인 생성자 함수의 경우: 전역 객체가 만들어지는 시점에 생성. 코드가 실행하기도 전에.
리터럴이나, Object 생성자 함수나, 사용자 정의 생성자 함수나~ 사실 다 똑같아. 체인의 깊이가 다를 뿐.
1. Person 생성자 함수의 프로토는 ~ Function.prototype. Function.prototype는 객체니까, 얘의 프로토는~ Object.prototype.
2. Person 객체의 프로토는 인스턴스니까 ~ Person.prototype. Person.prototype는 객체니까, 얘의 프로토는~ Object.prototype.
결국 체인의 꼭대기는 Object.prototype. 이런 부모 자식 관계 속에서 상속이 일어남.
왕엄마의 메서드 빌려. 그걸 또 딸이 빌려.
왕엄마는 빌릴데가 없지? 그래서 Object.prototype 의 프로토타입은 null
Calculator.prototype.add = (x, y) => x + y;
cal1.add = (x, y) => x + 2 * y;
cal1.add(1, 1); // 3
// 삭제하면 정상적으로 프로토타입 메서드 호출 (인스턴스 레벨에서 프로토타입 메서드를 변경, 삭제할 수는 없음, 하위레벨에서 프로토타입은 리드 온리)
delete cal1.add;
cal1.add(1, 1); // 2
그저 체이닝 상, 인스턴스 메서드가 프로토타입 메서드보다 우선순위가 높아.
Calculator.prototype = {
add(...){...},
constructor: Calculator, // 프로토타입 교체시 constructor 프로퍼티를 지정해줘야 바인딩이 유지
};
Object.setPrototypeOf(cal1, {...});
인스턴스 레벨의 경우 Calculator 생성자 함수의 prototype property가 변경된 프로토타입을 가리키지 않는다.
cal1 instanceof Object; // true
cal1 instanceof Calculator; // true
생성자함수랑 인스턴스가 프로토타입 체인 상에 존재해야.
getPrototypeOf(cal1) === Calculator.prototype; //
const obj = Object.create(null); // obj 는 프로토타입 없어, Object.prototype 의 메서드나 프로퍼티 사용 불가
프로토타입을 지정하면서 객체 생성 가능, 리터럴로 만든 객체도 체이닝에 포함 가능, new 연산자 필요 x
이런 애들은 인스턴스가 참조 불가, 왜냐? 프로토타입 체인 상에 있는게 아니니까
Math.random() / Object.getPrototypeOf()
전역객체에 있는 변수, 함수 -> 사실 전역객체가 진짜 객체 맞음... 프로퍼티 메서드 느낌이라
function(){
x = 10; // 선언하지도 않은 x에 재할당
}
obj = {};
use strict