일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- camera permission
- Each child in a list should have a unique "key" prop.
- github pdf
- 이미지 데이터 타입
- html
- dvh
- device in use
- Recoil
- adb connect
- 티스토리 성능
- ELECTRON
- adb pair
- rolldown
- ffi-napi
- camera access
- npm package
- nextjs
- animation
- electron-packager
- Failed to compiled
- custom printing
- react-native-dotenv
- github 100mb
- github lfs
- Git
- augmentedDevice
- silent printing
- Can't resolve
- react-native
- vercel git lfs
- Today
- Total
Bleeding edge
2022/08/17 - TIL 본문
19장 프로토 타입
19.1 객체지향 프로그래밍
명령어 또는 함수의 목록으로 보는 전통적인 명령형 프로그래밍을 벗어나
객체의 집합으로 프로그램을 표현하려는 프로그래밍 패러다임을 말한다.
객체지향 프로그래밍은 실세계의 실체를 인식하는 철학적 사고를 프로그래밍에 접목하려는 시도에서 시작한다. 사람에게는 다양한 속성이 있으나 우리가 구현하려는 프로그램에서는 사람의 이름과 주소라는 속성에만 관심이 있다고 가정하자. 이처럼 다양한 속성에서 프로그램에 필요한 속성만 간추려 내어 표현하려는 것을 추상화라고 한다.
속성을 통해 여러 개의 값을 하나의 단위로 구성한 복합적인 자료구조를 객체라한다. 객체지향 프로그래밍은 객체의 **상태를 나타내는 데이터(프로퍼티)**와 상태데이터를 조작할 수 있는 동작(메서드)을 하나의 논리적인 단위로 묶어서 생각한다.
19.2 상속과 프로토타입
상속은 객체지향 프로그램의 핵심 개념으로 어떤 객체의 프로퍼티 또는 메서드를 다른 객체가 상속받아 그대로 사용할 수 있는 것을 말한다.(중복을 제거하고 재사용성을 높인다). 자바스크립트는 프로토타입을 기반으로 상속을 구현한다.
19.3 프로토타입 객체
프로토타입 객체란 객체지향 프로그래밍의 근간을 이루는 객체 간 상속을 구현하기 위해 사용한다.
프로토타입은, 상위 객체의 역활을 하는 객체의 프로퍼티를
하위 **자식이 자유롭게 사용할 수 있다.**
모든 객체는 [[Prototype]]이라는 내부슬롯을 가지며, 이 내부 슬롯의 값은 프로토타입의 참조다. . 즉 객체가 생성될 때 객체 생성방식에 따라 프로토타입이 결정되고 [[Prototype]]에 저장된다.
객체 리터럴에 의해 생성된 객체의 프로토타입은 Object.prototype이고, 생성자 함수에 의해 생성된 객체의 프로토타입은 prototype 프로퍼티에 바인딩 되어 있는 객체다.
모든 객체는 하나의 프로토타입을 갖는다. 모든 프로토 타입은 생성자 함수와 연결되어있다. 객체와 프로토타입과 생성자 함수는 서로 연결되어 있다
19.3.1 proto 접근자 프로퍼티
모든 객체는 proto 접근자 프로퍼티를 통해 자신의 프로토타입 즉[[Prototype]] 내부 슬롯에 간접적으로 접근할 수 있다.
19.3.1.1 proto 는 접근자 프로퍼티다.
const obj ={};
const parent = {x:1};
obj.__proto__ //get함수
obj.__proto__ = parent; //set함수
10.3.1.2 proto 접근자 프로퍼티는 상속을 통해 사용된다
const person = {name : 'Lee'};
//person 객체는 __proto__ 프로퍼티를 소유하지 않는다.
console.log(person.hasOwnProperty('__proto__'));
//__proto__ 프로퍼티는 모든 객체의 프로토타입 객체인 Object.prototype의
//접근자 프로퍼티다.
console.log(Object.getOwnPropertyDescriptor(Object.prototype, '__proto__'))
//모든 객체는 Object.prototype의 접근자 프로퍼티 __proto__를 상속받아
//사용할 수 있다.
console.log({}.__proto__ ===Object.prototype); //true
10.3.1.3 proto 접근자 프로퍼티를 통해 프로토타입에 접근하는 이유
상호 참조에 의해 프로토타입 체인이 생성되는 것을 방지하기 위해서다.
→프로토타입 체인은 단방향 링크드 리스트로 구현되어야 한다.
→무한 루프 탐색을 막을 수 있다
10.3.1.4 proto 접근자 프로퍼티를 코드 내에서 직접 사용하는 것은 권장하지 않는다.
모든 객체가 proto 접근자 프로퍼티를 사용할 수 있는 것이 아니기 때문이다. 나중에 살펴보겠지만, 직접 상속을 통해 다음과 같이 Object.prototype을 상속 받지 않는 객체를 생성할 수도 있기 때문에 _proto_접근자 프로퍼티를 사용할 수 없는 경우가 있다
const obj = Object.create(null);
console.log(obj.__proto__);//undefined
console.log(Object.getPrototypeOf(obj)); //null
//__proto__보다 Object.getPrototypeOf 메서드를 사용하는 편이 좋다.
만일, proto 접근자 프로퍼티 대신
프로토타입의 참조를 취득하고 싶은 경우→ Object.getPrototypeOf 메서드를 사용하고
프로토타입을 교체하고 싶은 경우→Object.setPrototypeOf 메서드를 사용할 것을 권장한다
19.3.2 함수 객체의 prototype 프로퍼티
함수 객체만이 소유하는 prototype 프로퍼티는 생성자 함수가 생성할 인스턴스의 프로토타입을 가리킨다. (non-constructor인, 화살표 함수와 ES6의 축약표현으로 생성한 함수는 프로토타입을 생성하지 않는다)
const arrow_function = () => {];//화살표 생성자 함수
const abbr_function_object = {abbr_function()};//축약 표현
arrow_function_example = new arrow_function;
(function(){}).hasOwnProperty('prototype'); //true
({}).hasOwnproperty('prototype')//false
console.log(arrow_function_example.hasOwnProperty('prototype')//false
console.log(arrow_function_example.prototype)//undefined
console.log(arrow_function_example.hasOwnProperty('prototype')//false
console.log(abbr_function_object.abbr_function.hasOwnProperty('prototype');
console.log(abbr_function_object.abbr_function.prototype)
모든 객체가 __proto __접근자 프로퍼티를 가지고 있고, 함수 객체가 prototype을 가지고 있지만, 결국 동일한 프로토타입을 가리킨다. 하지만 사용하는 주체가 다르다
구분 소유 값 사용 주체 사용 목적
__ proto__ | ||||
접근자 프로퍼티 | 객체 | 프로토타입의 참조 | 모든 객체 | 객체가 자신의 프로토타입에 접근 또는 교체하기 위해 사용 |
prototype | ||||
프로퍼티 | constructor | 프로토타입의 참조 | 생성자 함수 | 생성자 함수가 자신이 생성할 객체(인스턴스)의 프로토타입을 할당하기 위해 사용 |
function generator_function(name){
this.name = name;
}
const instance = new generator_function('name');
console.log(generator_function.prototype ===instance.__proto__
19.3.3 프로토타입의 constructor 프로퍼티와 생성자 함수
모든 프로토타입은 constructor 프로퍼티를 갖는다. constructor는, prototype 프로퍼티로 자신을 참조하고 있는 생성자 함수를 가리킨다
이 연결은 생성자 함수가 생성될 때, 연결된다
function generator_function (name){
this.name = name;
}
const instance = new generator_function('name')
console.log(instance.constructor === generator_function);//true
19.4 리터럴 표기법에 의해 생성된 객체의 생성자 함수와 프로토타입
생성자 함수에 의해 생성된 인스턴스는 constructor 프로퍼티에 의해 생성자 함수와 연결된다.
- new 연산자를 사용한 방법
function generator_function (name){
this.name = name;
}
const obj = new Object();
const func = new Function('x', 'y', 'return x+y');
const instance = new generator_function('name');
console.log(obj.constructor === Object)//true;
console.log(func.constructor ===Function)//true
console.log(instance.constructor ===generator_function)//true
리터럴 표기법에 의한 프로토타입도 존재하지만, 반드시, constructor 프로퍼티가 반드시 생성자 함수를 가리킨다고 볼 수는 없다
Object 생성자 함수에 인수를 전달하지 않거나 undefined 또는 null을 인수로 전달하면서 호출하면 내부적으로는 추상 연산인 OrdinaryObjectCreate를 호출하여 Object.prototype을 프로토타입으로 갖는 빈 객체를 반환한다
Object 생성자 함수 호출과 객체 리터럴의 평가는 OrdinaryObjectCreate를 호출하여
빈객체를 생성하는 점에서 동일하나 new.target의 확인이나 프로퍼티를 추가하는
처리 등 세부 내용은 다르다.
따라서 객체 리터럴에 의해 생성된 객체는 Object 생성자 함수가 생성한 객체가 아니다.
함수 객체는 Function 생성자 함수를 호출하여 생성한 함수는 렉시컬 스코프를
만들지 않고 전역 함수인 것처럼 스코프를 생성하며 클로저도 만들지 않는다
따라서 함수 선언문과 함수 표현식을 평가하여 함수 객체를 생성하는 것은 Function
생성자가 아니다.
//하지만, constructor는 Function으로 나온다
프로토타입은 생성자 함수와 더불어 생성되며 prototype, constructor 프로퍼티에 의해 연결되어 있다. 프로토타입과 생성자함수는 단독이 아닌 항상 쌍으로 존지한다
19.5 프로토타입의 생성 시점
프로토타입은 생성자 함수가 생성되는 시점에 더불어 생성된다.
생성자함수 : [사용자가 정의한 생성자 함수, 자바스크립트 빌트인 생성자함수]
19.5.1 사용자 정의 생성자 함수와 프로토타입 생성시점
화살표함수, ES6의 메서드 축약표현으로 정의 하지 않고(non-constructor),
일반 함수(함수 선언문, 함수 표현식)으로 정의한 함수 객체는
new 연산자와 함께 <생성자 함수>로써 호출할 수 있다.
constructor는 함수 정의가 평가되어 함수 객체를 생성하는 시점에 프로토타입도 더불어 생성된다 ⇒ non-constructor는 프로토타입이 생성되지 않는다.
함수 선언문은 런타임 이전에 먼저 실행된다. 함수 선언문으로 생성자 함수는 어떤 코드보다 먼저 평가되어 함수 객체가 된다. 이때 프로토타입도 더불어 생성된다. 생성된 프로토타입은 생성자 함수의 prototype프로퍼티에 바인딩된다.
19.5.2 빌트인 생성자 함수와 프로토타입 생성 지점
Object,String,Number,Function,Array,RegExp,Date,Promise 등의 빌트인 생성자 함수도 생성자 함수가 생성되는 시점에 프로토타입이생성된다.
모든 빌트인 생성자 함수는 전역 객체가 생성되는 시점에 생성된다. 빌트인 생성자 함수의 prototype 프로퍼티에 바인딩된다
객체가 생성되기 이전에 생성자 함수와 프로토타입은 이미 객체화되어 존지한다. 생성자 함수 또는 리터럴 표기법으로 객체를 생성하면 프로토타아입은 생성된 객체의 [[ Prototype]]내부 슬롯에 할당된다
19.6 객체 생성 방식과 프로토타입의 결정
모든 객체는 추상 연산 OrdinryObjectCreate로 생성된다는 공통점이 있다.
OrdinaryObjectCreate는 빈 객체르 생성한 후, 객체에 추가할 프로퍼티 목록이 인수로 전달된경우 프로퍼티를 객체에 추가한다.
인수로 전달받은 프로토타입을 자신이 생성한 객체의 [[ Prototype]]내부 슬롯에 할당한다음 생성한 객체를 반환한다
프로토타입은 추상 연산 OOC에 전달되는 인수에 의해결정되며 이 인수는 객체가 생성되는 시점에 객체 생성방식에 의하여 결정된다
19.6.1 객체 리터럴에 의해 생성된 객체의 프로토 타입
const obj = {x:1}; //객체 리터럴에 의해 생성된 객체의 프로토타입
=> OrdinaryObjectCreate(Object.prototype)
//객체 리터럴(obj)의 프로토타입은 Object.prototype이다
//obj에는 constructor와 hasOwnProperty는 없지만 Object.prototype에서
//상속되었기 때문에 사용할 수 있다
console.log(obj.constructor===Object, obj.hasOwnProperty('x'))//true true
19.6.2 Object 생성자 함수에 의해 생성된 객체의 프로토 타입
const obj = new Object()
obj.x = 1
//19.6.1과 같다
19.6.1과 19.6.2의 차이는 Object의 프로퍼티 추가 방식이 차이가 난다.
19.6.3 생성자 함수에 의해 생성된 객체의 프로토 타입
function GeneratorFunction(x){
this.x = x;
}
const instance = new GeneratorFunction('example');
//new 연산자와 함꼐 생성자 함수를 호출하여 인스턴스를 생성하면
=>OrdinaryObjectCreate(GeneratorFunction.prototype)
//생성자 함수에 의해 생성되는 객체의 프로토타입은 생성자 함수에 바인딩된 객체다.
//추상 연산 OrdinaryObjectCreate에 의해 생성자 함수와 생성자 함수의
//prototype 프로퍼티에 바인딩되어 있는 객체와 생성된 객체 사이에 연결이 만들어진다.
//Object.prototype은 다양한 빌트인 메서드를 갖고있다.
//하지만 사용자 정의함수와 더불어 생성된 프로토타입의 프로퍼티는 constructor뿐이다
constrcutor가 아닌 다른 프로토타입 프로퍼티를 상속하는 방법은 다음과 같다.
function GeneratorFunction(x){
this.x = x;
}
GeneratorFunction.prototype.prototypeMethod = function(){
console.log(`this is ${this.x}`
}
const instance = new GeneratorFunction('example');
=>OrdinaryObjectCreate(GeneratorFunction.prototype)
instance.prototypeMethod() //this is example
19.7 프로토타입 체인p286그림 봐둘 것
생성 함수에 의해 받은 prototype 프로퍼티를 제외하고, Object.prototype도 상속되어 사용할 수 있다. 이것이 바로 프로토타입 체인이다.
자바스크립트는 객체의 프로퍼티에 접근했을 때 해당 객체에 접근하려는 프로퍼티가 없다면 [[ Prototype]] 내부 스롯의 참조를 따라 자신의 부모 역활을 하는 프로토타입 프로퍼티를 순차적으로 검색한다. 이를 프로토타입 체인이라고 하며, 프로토타입 체인은 자바스크립트가 객체지향 프로그래밍의 상속을 구현하는 매커니즘이다.
프로토타입 체인의 최상위에 위치하는 객체는 언제나 Object.prototype이다. 따라서 모든 객체는 Object.prototype을 상속받는다. Object.Prototype을 프로토 타입의 종점이라고한다.
Object.prototype의 프로토타입 즉 [[Prototype]]내부 슬롯 값은 null이다.
⇒스코프체인 : 식별자 검색을 위한 매커니즘
⇒프로토타입 체인 : 상속과 프로퍼티 검색을 위한 매커니즘
스코프체인과 프로토타입체인은 서로 연관없이 별도로 동작하는 것ㅅ이 아니라 서로 협력하여 식별자와 프로퍼티를 검색하는데 사용된다.
19.8 오버라이딩과 프로퍼티 섀도잉
const GeneratorFunction = (function(){
//생성자 함수
function GeneratorFunction(x){
this.x = x;
}
GeneratorFunction.prototype.prototypeMethod = function(){
console.log(`this is ${this.x}`
}
return GeneratorFunction;
}());
const instance = new GeneratrorFunction('example');
//오버라이딩
instance.prototypeMethod = function (){
console.log(`this is ${this.x} 2`)
}
instance.prototypeMethod();
//this is example ->this is example 2로 프로퍼티 섀도잉이 되었다
//오버라이딩이 된것은 삭제를 통해서 볼 수 있다.
delete instance.prototypeMethod
instance.prototypeMethod();
//this is example1
delete instance.prototype.prototypeMethod
instance.prototypeMethod();
//Type.Error instance.prototypeMethod is not a function
19.9 포로토타입의 교체
19.9.1 생성자 함수에 의한 프로토타입 교체
const GeneratorFunction = (function(){
//생성자 함수
function GeneratorFunction(x){
this.x = x;
}
GeneratorFunction.prototype ={
prototypeMethod(){
console.log(`this is ${this.x} 2`)
//constructor : GeneratorFunction
}
}
return GeneratorFunction;
}());
const instance = new GeneratorFunction('example')
console.log(instance.constructor === GeneratorFunction,
instance.constructor ===Object)//false true
//주석처리가되어있는 constructor을 풀면,
//console.log(instance.constructor === GeneratorFunction,
//instance.constructor ===Object)//true false가 나온다
생성자함수에 의한 프로토타입 교체를 한 prototype에는 constructor 프로퍼티가 없다.
instance의 생성자 함수를 검색하면 GeneratorFunction이 아닌 Object가 나온다
19.9.2 인스턴스에 의한 프로토타입의 교체
function GeneratorFunction(x){
this.x = x;
}
const instance = new GeneratorFunction('example');
const parent = {
prototypeMethod(){
console.log(`this is ${}`)
}
}
Object.setPrototypeOf(instance, parent)
//instance의 프로토타입을 parent로 바꾼다
//instance.__proto__ = parent;
//위와 아래코드가 정확히 같다.
//이 경우에도 constructor 프로퍼티가 없으므로, 생성자 함수를 검색하면
//GeneratorFunction이 아닌 Object가 나온다
19.10 instanceof 연산자
function GeneratorFunction(x){
this.x = x;
}
const instance = new GeneratorFunction('example')
/*
instance(객체) instanceof GeneratorFunction(생성자 함수) === type of Boolean
*/
function GeneratorFunction(x){
this.x = x;
}
const instance = new GeneratorFunction('example')
console.log(
instance instanceof GeneratorFunction, //true
instance instanceof Object //true, instance의 프로토타입 체인스코프에 있으니 true
)
19.11 직접상속
19.11.1 Object.create에 의한 직접 상속
//
Object.create(null)
Object.create(Object.prototype)
//
- new 연산자 없이도 객체를 생성할 수 있다
- 프로토타입을 지정하면서 객체를 생성할 수 있다
- 객체 리터럴에 의해 생성된 객체도 상속받을 수 있다.
19.11.2 객체 리터럴 내부에서 product 에 의한 직접 상속
Object.create매서드에 의한 직접 상속은 두번째 인자로 프로퍼티를 정의하는 것은 번거롭다.
ES6에서는 객체 리터럴 내부에서 __proto __를 이용하여 직접상속을 구현할 수 있다.
const obj = {x:10}
const inheritedObj ={
y:20,
__proto__ : obj
//inheretedObj -> obj -> null
}
/*
Object.create가 복잡한것을 직접 느껴보자
const obj = Object create(myProto, {
y:{value:20, writable:true, enumerable:true, configurable:true}
})
*/
console.log(obj.x, obj,y)// 10 20
19.12 정적프로퍼티/메서드
정적 프로퍼티/메서드는 생성자함수로 인스턴스를 생성하지 않아도 참조/호출할 수 있는 프로퍼티 매서드를 말한다.
function GeneratorFunction(x){
this.x = x;
}
GeneratorFunction.prototype.prototypeMethod = function(){
console.log(`this is ${example}`)
}
GeneratorFunction.staticProperty = 'static property';
GeneratorFunction.staticMethod = function(){
console.log('static method');
}
const instance = new GeneratorFunction('example')
GeneratorFunction.staticMethod() //static method
instance.staticMethod()//TypeError
//정적 매소드는 생성자 함수에서만 호출이 가능하다.
//인스턴스에서는 프로토타입 체인상에 있는 프로퍼티 메소드를 호출할 수 있다
Object.prototype.isPrototypeOf를 Object#isPrototypeOf처럼 #을 이용해서 표기하는 경우도 있다
'ConnecTo' 카테고리의 다른 글
2022/08/19 - TIL (0) | 2022.08.19 |
---|---|
2022/08/18 - TIL (0) | 2022.08.18 |
2022/08/16 - TIL (0) | 2022.08.16 |
2022/08/12 - TIL (0) | 2022.08.12 |
2022/08/11 - TIL (0) | 2022.08.11 |