예제에 의한 자바스크립트 프로토타입

JavaScript의 프로토타입은 객체 간에 공통 기능을 공유하는 메커니즘입니다. 그들은 강력하지만 때때로 혼란스럽습니다. 예제를 통해 프로토타입 동작을 살펴보겠습니다. 브라우저의 개발자 도구에서 아래 예제를 시도하고 실험할 수 있습니다.

개체 인스턴스를 생성하기 위해 생성자 함수Object로 시작합니다.

typeof Object; // function

그것은 prototype , toString 등과 같은 유용한 방법을 가진 valueOf 속성을 가지고 있습니다.

Object.prototype; // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}

객체 생성의 두 가지 방법

var obj1 = new Object();
var obj2 = {};

생성 시 모든 개체 인스턴스는 __proto__ 속성을 받습니다.

var obj = {};
obj.__proto__; // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
Object.getPrototypeOf는 이전__proto__ 속성을 현대적으로 대체합니다.

var obj = {};
Object.getPrototypeOf(obj) === obj.__proto__; // true

개체의 __proto__Object.prototype는 완전히 동일한 개체입니다.

var obj = {};
obj.__proto__ === Object.prototype; // true

개체는 다르지만 동일한 프로토타입을 공유합니다.

var obj1 = {};
var obj2 = {};
obj1 === obj2; // false
obj1.__proto__ === obj2.__proto__; // true

프로토타입 체인은 null로 종료됩니다.

var obj = {}
obj.__proto__.__proto__ // null

프로토타입에 추가된 속성은 모든 인스턴스에서 사용할 수 있습니다(내장 프로토타입을 수정하는 것은 권장되지 않습니다!).

var obj1 = {};
var obj2 = {};
obj2.foo // undefined
obj1.__proto__.foo = 'bar';
obj2.foo; // bar

프로토타입 없이 개체를 만드는 것이 가능합니다. 이 경우 toString , valueOf , e.t.c와 같은 편리한 방법입니다. 사용할 수 없습니다

var obj1 = {a: 1};
var obj2 = Object.create(null);
obj2.__proto__; // undefined
obj1 + ''; // "[object Object]"
obj2 + ''; // Uncaught TypeError: Cannot convert object to primitive value

개체__proto__의 링크는 언제든지 변경할 수 있습니다.

var obj = {};
obj.toString(); // "[object Object]"
Object.setPrototypeOf(obj, null);
obj.toString(); // Uncaught TypeError: obj.toString is not a function
Object.setPrototypeOf(obj, Object.prototype);
obj.toString(); // "[object Object]"

원하는 길이의 프로토타입 체인을 구성할 수 있습니다.

var obj1 = {};
var obj2 = Object.create(obj1);
obj2.__proto__ === obj1; // true

개체에서 속성을 찾을 수 없는 경우 프로토타입 체인에서 맨 위로 검색됩니다.

var obj1 = {a: 1};
var obj2 = Object.create(obj1);
obj2.hasOwnProperty('a'); // false
obj2.a // 1

속성 생성은 프로토타입이 아닌 현재 개체에서 발생합니다.

var obj1 = {a: 1};
var obj2 = Object.create(obj1);
obj2.hasOwnProperty('a'); // false
obj2.a; // 1
obj2.a = 2;
obj2.hasOwnProperty('a'); // true
obj2.a; // 2
obj2.__proto__.a; // 1

속성 값은 현재 개체에서 먼저 검색됩니다. 찾지 못한 경우 속성을 찾거나 프로토타입 체인이 종료될 때까지 프로토타입 체인에서 검색이 계속됩니다. 이로 인해 아래 게시물에 설명된 대로 성능 문제가 발생할 수 있습니다.





프리미티브는 자체 프로토타입을 가지고 있습니다.

var n = 1;
n.__proto__ === Number.prototype; // true
n.__proto__.__proto__ === Object.prototype; // true


Object.prototype의 프로토타입을 변경할 수 없습니다.

Object.setPrototypeOf(Object.prototype, {}); // Uncaught TypeError: Immutable prototype object '#<Object>' cannot have their prototype set


순환 프로토 체인은 금지됩니다.

var obj1 = {};
var obj2 = {};
Object.setPrototypeOf(obj1, obj2);
Object.setPrototypeOf(obj2, obj1); // Uncaught TypeError: Cyclic __proto__ value


함수 생성자를 만들고 모든 인스턴스에서 사용할 수 있는 유용한 메서드로 프로토타입을 확장하는 것이 일반적이었습니다.

var Cat = function() {};
Cat.prototype.sayHi = function() {return 'meow'};
var cat = new Cat();
cat.__proto__ === Cat.prototype; // true
cat.sayHi(); // "meow"


ES2015 클래스는 프로토타입의 구문 설탕입니다.

class Animal {};
var cat = new Animal();
cat.__proto__ === Animal.prototype; // true


클래스 확장은 프로토타입 체인 확장을 의미합니다.

class Animal {};
class Cat extends Animal {};
var cat = new Cat();
cat.__proto__.__proto__ === Animal.prototype; // true


의견 섹션에서 프로토타입 작업의 예를 공유하십시오.

추가 자료



MDN

You Don't Know JS

The Modern JS Tutorial

좋은 웹페이지 즐겨찾기