[Effective JavaScript] __ proto __ 보다 Object.getPrototypeOf()를 사용하자

김범식·2023년 7월 14일
0

Effective JavaScript

목록 보기
28/33
post-thumbnail

_ proto _ 와 Object.getPrototypeOf()


두가지 모두 javascript에서 프로토 타입에 접근하는데 사용되는 메커니즘이다. 하지만 사용 방법과 결과적인 동작에 차이가 있는데 아래 코드를 통해 차이점을 알아보자

예시 1

function Parent(name,age){
  this.name = name;
  this.age = age;
}

Parent.prototype.greet = function(){
  console.log(this.name+"! hello")
}

var child = new Parent("홍길동",12);

console.log(child.__proto__ === Object.getPrototypeOf(child)) //출력 :true

두 가지 모두 자신이 바라보고있는 프로토타입을 가리킨다.

예시 2

// 부모 객체
var parent = {
  greet: function() {
    console.log('Hello from parent');
  }
};

// 자식 객체
var child = {};

// __proto__를 사용하여 프로토타입 설정
child.__proto__ = parent;

// Object.getPrototypeOf()를 사용하여 프로토타입 확인
var proto = Object.getPrototypeOf(child);

// 결과 확인
console.log(proto === parent); // true
proto.greet(); // Hello from parent

__proto__ 는 프로토타입을 설정할 수 있다.

실제로 Object.getPrototypeOf() 를 통해 확인한 프로토타입이 parent와 동일한것을 보면 알수 있다.



Object.create()


javascript에서 생성하는 메서드이다. 이 메서드를 사용하면 새로운 객체를 생성하고 해당 객체의 프로토 타입을 지정할 수있다.



사용예 1

// 프로토타입 객체
var personPrototype = {
	greet:function(){
		console.log("Hello, "+this.name+"!");
	}
}

// 새로운 객체 생성
var person = Object.create(personPrototype);

// 프로토 타입 객체의 속성 설정
person.name = "Alice";

// 객체의 메서드 호출
person.greet(); //Hello, Alice!
  • Object.create로 새로운 객체를 만들때 프로토타입을 미리 지정할 수 있다.
  • 프로토 타입을 미리 지정했기 때문에 person객체에서 greet() 함수를 불러올 수 있다.



사용예 2

// 프로토타입 객체
var personPrototype = {
  greet: function() {
    console.log('Hello, ' + this.name + '!');
  }
};

// 새로운 객체 생성 및 프로퍼티 설정
var person = Object.create(personPrototype, {
  name: {
    value: 'Alice', //값
    writable: true,  //변경 가능한지 여부
    enumerable: true, //열거 가능한지 여부
    configurable: true //프로퍼티의 설정을 변경할 수 있는지 여부
  },
  age: {
    value: 25,
    writable: false,
    enumerable: true,
    configurable: false
  }
});

// 객체의 메서드 호출
person.greet(); // Hello, Alice!

// 프로퍼티 값 변경 시도
person.name = 'Bob'; // 가능
person.age = 30; // 불가능

// 프로퍼티 열거
for (var prop in person) {
  console.log(prop + ': ' + person[prop]);
}

// 열거된 프로퍼티
// "name: Bob"
// "age: 25"
// "greet: function() {
//     window.runnerWindow.proxyConsole.log('Hello, ' + this.name + '!');
//   }"
  • 두번째 매서드에는 객체에서 사용할 속성을 지정할 수 있다.
  • person은 이제 name, age 두개의 속성을 사용할 수 있다.
  • 또한 열거형으로 설정했기 때문에 향상된 for문을 통해 열거할 수 있다.



proto 보다 Object.getPrototypeOf()를 사용하자


ES5는 객체의 프로토타입을 가져오기 위한 표준 API로 Object.getPrototypeOf를 도입했지만, 많은 자바스크립트 엔진들은 이미 동일한 목적으로 __proto__ 프로퍼티를 제공해 왔다.

그렇다고 모든 프로퍼티가 Object.getPrototypeOf를 지원하는것도 아니다. 실행 환경들은 null 프로토타입을 가지는 객체를 ㅅ로 다르게 처리한다.



proto 사용

어떤 실행 환경에서 __ proto __Object.prototype을 상속하고 , 따라서 null프로토타입을 가지는 객체는 특별한 __ proto __프로퍼티를 가지지 않는다.

var empty = Object.create(null); //프로토 타입이 없는 객체 
"__ proto __" in empty; //false; => empty라는 객체에 prototype프로퍼티가 있는지 확인한다.

이것이 다른 몇몇 환경에서는 다음과 같이 처리된다.

var empty = Object.create(null); //프로토 타입이 없는 객체 
"__ proto __" in empty; //true; => empty라는 객체에 prototype프로퍼티가 있는지 확인한다.



Object.prototypeOf() 사용

__ proto__는 모든 객체를 어지럽히는 많은 버그를 초래한다. 때문에 Object.getPrototypeOf를 사용하는 것이 좋다. 혹은 __ proto __를 사용해 Object.getPrototypeOf를 구현하는 방법은 다음과 같다.

if(typeof Object.getPrototypeOf === 'undefined'){
	Object.getPrototypeOf = function(obj){
		var t = typeof obj;
		if((!obj || (t !==' Object" && t !== "function)){
			throw new TypeError("not an object");
		}
		return obj.__proto__;
		};
}
  • 객채나 함수가 맞으면 prototype을 반환한다.



기억할 점

  • 비표준 __ proto __ 프로퍼티를 사용하기 보다 표준을 준수하는 Object.getPrototypeOf()를 사용하자
  • __ proto__를 지원하고 ES5를 지원하지 않는 실행 환경에서 Object.getPrototypeOf를 구현하자
profile
frontend developer

0개의 댓글