프로토타입 상속

다른 데이터 유형과 마찬가지로 객체는 내장된 Object 프로토타입에서 속성과 메서드를 상속합니다. 즉, 결과 객체에는 정의한 속성과 프로토타입에서 상속된 메서드를 포함하는 프로토타입 속성이 모두 포함됩니다.

let myObject = {
    'booleanValue' : true
};

myObject;
> Object { booleanValue: true }
    booleanValue: true
    [[prototype]]: Object { … }
            __defineGetter__: function __defineGetter__()
            __defineSetter__: function __defineSetter__()
            __lookupGetter__: function __lookupGetter__()
            __lookupSetter__: function __lookupSetter__()
            __proto__: …
                constructor: function Object()
                hasOwnProperty: function hasOwnProperty()
                isPrototypeOf: function isPrototypeOf()
                propertyIsEnumerable: function propertyIsEnumerable()
                toLocaleString: function toLocaleString()
                toString: function toString()
                valueOf: function valueOf()
                <get __proto__()>: function __proto__()
                <set __proto__()>: function __proto__()

프로토타입 속성은 속성 키로 직접 액세스할 수 없습니다. 이전 예에서 볼 수 있듯이 이는 브라우저의 개발자 콘솔과 프로토타입의 속성 키 문서 소스에서 사용된 [[prototype]] 또는 <prototype> 표기법을 통해 암시됩니다.

// Chrome:
let emptyObject = {};

emptyObject;
> {}
  [[prototype]]: Object
// Firefox:
let emptyObject = {};

emptyObject;
> Object {  }
  <prototype>: Object { … }

모든 일반 브라우저에서 사실상의 표준으로 __proto__를 사용하지만 공식적으로 표준화되지 않았으므로 프로덕션 코드에서는 이를 피해야 합니다.

let emptyObject = {};

emptyObject.__proto__;
> Object { … }
    __defineGetter__: function __defineGetter__()
    __defineSetter__: function __defineSetter__()
    __lookupGetter__: function __lookupGetter__()
    __lookupSetter__: function __lookupSetter__()
    __proto__:
        constructor: function Object()
        hasOwnProperty: function hasOwnProperty()
        isPrototypeOf: function isPrototypeOf()
        propertyIsEnumerable: function propertyIsEnumerable()
        toLocaleString: function toLocaleString()
        toString: function toString()
        valueOf: function valueOf()
        <get __proto__()>: function __proto__()
        <set __proto__()>: function __proto__()

대신 내장된 Object.getPrototypeOf()Object.setPrototypeOf() 메서드를 사용하여 객체의 [[Prototype]]에 직접 액세스하고 수정할 수 있습니다.

let myObj = { "value" : 5 };
let protoParent = { "protoValue" : true };

myObj;
Object { value: 5 }
    value: 5
    <prototype>: Object { … }

Object.getPrototypeOf( myObj );
> Object { … }
    __defineGetter__: function __defineGetter__()
    __defineSetter__: function __defineSetter__()
    __lookupGetter__: function __lookupGetter__()
    __lookupSetter__: function __lookupSetter__()
    __proto__:
    constructor: function Object()
    hasOwnProperty: function hasOwnProperty()
    isPrototypeOf: function isPrototypeOf()
    propertyIsEnumerable: function propertyIsEnumerable()
    toLocaleString: function toLocaleString()
    toString: function toString()
    valueOf: function valueOf()
    <get __proto__()>: function __proto__()
    <set __proto__()>: function __proto__()

Object.setPrototypeOf( myObj, protoParent );
> Object { value: 5 }
    value: 5
    <prototype>: Object { protoValue: true }

상속된 속성과 작성자가 정의한 속성을 구분하기 위해 후자를 일반적으로 객체의 '자체 속성'이라고 합니다.

기본 제공되는 Object.hasOwn() 메서드는 지정된 속성이 객체의 직접 속성인 경우 true를 반환하고 속성이 상속되거나 존재하지 않으면 false를 반환합니다. 가능하면 Object.create()를 지원하지 않는 상속된 hasOwnProperty() 메서드 대신 Object.hasOwn()를 사용하세요.

let myObject = {
    'myValue' : 100
};

Object.hasOwn( myObject, 'myValue' );
> true

myObject.__proto__; // The Object prototype inherited by `myObject` is present:
> Object { … }

Object.hasOwn( myObject, '__proto__' ); // The Object prototype inherited by `myObject` is not an "own property:"
> false

이해도 테스트

__proto__를 사용하면 안 되는 이유는 무엇인가요?

표준화되지 않았습니다.
많은 브라우저에서 지원되지 않습니다.
이렇게 하면 향후 코드 유지관리자가 혼란을 겪을 수 있습니다.