Object.create() 메소드에 대해서 좀 더 자세히 알아보겠습니다.
new 연산자와 Object.create() 메소드로 생성하던 둘 다 객체를 생성합니다.
하지만 쓰임세가 조금 다릅니다. 그럼 어떤 쓰임세의 차이가 있는 것일까요?
뒤이어 예제 코드와 함께 자세하게 설명하겠지만 우선 간략하게 말씀드리면,
상속과 확장을 위한 템플릿 개념으로 쓸 때는 Object.create() 메소드로 객체를 생성하면됩니다.
반면, 상속을 받아서 데이터 바인딩에 직접적으로 사용하려면 new 연산자를 쓰셔서 객체를 생성하면 됩니다.
아래에 예제 코드로 설명하겠습니다.
1. 객체생성 비교
function test1() {
this.a = 10;
this.b = 20;
this.getA = function() {
return this.a;
}
};
test1.prototype.getB = function() {
return this.b;
}
let t1 = Object.create(test1.prototype);
console.log(t1);
let t2 = new test1();
console.log(t2);
Object.create() 메소드로 생성한 t1은 객체는 빈 객체만 생성되고 test1의 속성과 메소드를 호출하면 undefined로 표시됩니다. 또한 t1 객체는 자신의 생성자를 만들지 않습니다.
반면, new 연산자로 객체를 생성하고 test1의 속성과 메소드를 호출하면 정상적으로 출력됩니다.
그럼 Object.create() 메소드로 객체를 생성하면 왜 test1의 속성과 메소드를 호출할 수 없을까요?
위의 console.log(t1)의 결과값 이미지에서 볼 수 있듯시, __proto__ 안에 프로토타입객체인 test1의 속성과 메소드가 있습니다.
cf) proto 혹은 [[prototype]]이란
함수를 포함한 모든 객체가 가지고 있는 인터널 슬롯이다.
객체의 입장에서 자신의 부모 역할을 하는 프로토타입 객체를 가리키며, 함수 객체의 경우 Function.prototype를 가리킨다.
즉, t1객체에서의 proto는 부모의 정보만 나타낼뿐 상속해서 사용할 수 없습니다.
부모의 속성과 메소드를 사용하고 싶다면 new 연산자를 활용해서 객체를 생성해야합니다.
여기서 new 연산자가 왜 부모의 속성과 메소드를 인스턴스 객체에 만들어주는지를 아시려면, new 연산자의 암묵적인 메커니즘을 알아야합니다.
new 연산자의 암묵적인 메커니즘
new 연사자를 사용해서 인스턴스 객체를 만들기 위해 함수를 호출하면, 빈 객체를 만들어서 함수에 빈 객체를 전달해줍니다.
함수에 this 키워드는 생성된 빈 객체가 됩니다. this를 통해서 함수 내에 선언된 속성과 메서드를 빈 객체에 생성합니다.
또한 함수가 종료되면 return 값으로 this를 반환합니다.
이로 인해 인스턴스 객체가 생성되는 것입니다. 이러한 과정 때문에 함수 내에 return을 선언하지 않아도 됩니다.
new 연산자를 사용하시면, 함수의 인스턴스 객체를 만들면 일반 객체 프토타입을 코드로 연결시켜 놓은 걸 훨씬 더 단순하고 간편하게 객체의 상속관계를 만들 수 있습니다.
하지만 이번 세션에서는 new 연산자보다 Object.create()로 객체를 생성하는 방법을 다룹니다. 참고 사항으로만 알아두시면 좋을 것 같습니다. 그리고 사실 new 연사자로 객체를 생성하는 것이 더 쉬울 것 같습니다 ㅠㅜ
2. 상속과 확장
그럼 Object.create()는 어떨 때 사용하면 좋을까요?
객체 간에 상속을 통해서 속성이나 메소드를 확장할 때 쓰면 좋습니다.
function test1() {
this.a = 10;
this.b = 20;
this.getA = function() {
return this.a;
}
};
test1.prototype.getB = function() {
return this.b;
}
function test2() {
test1.apply(this,arguments);
this.c = 30;
this.getC = function() {
return this.c;
}
};
test2.prototype = Object.create(test1.prototype);
test2.prototype.constructor = test2;
test2.prototype.d = 40;
test2.prototype.getD = function() {
return this.d;
}
let testObject = new test2();
console.log(testObject); // 이미지 참조
console.log(testObject.a); // 10
console.log(testObject.b); // 20
console.log(testObject.c); // 30
console.log(testObject.d); // 40
console.log(testObject.getA()); // 10
console.log(testObject.getB()); // 20
console.log(testObject.getC()); // 30
console.log(testObject.getD()); // 40
test1 객체를 test2객체가 상속받고 testObject 객체를 생성했습니다.
위의 예제 코드로 객체를 상속 확장하는 과정을 나타냈습니다.
test1의 속성과 메소드를 test2가 상속하여 참조합니다.
test2 선언 시 apply 메소드를 사용했습니다.
apply 메소드란 test1의 생성자에 test2의 매개변수, 속성, 메소드 드을 적용하는 메소드입니다.
그 다음 test2.prototype = Object.create(test1.prototype); 코드를 통해서 test2의 프로토타입 객체가 test1라는 것을 선언합니다.
그리고 test2는 생성자는 생성하지 않기 때문에 test2.prototype.constructor = test2; 코드로 test2의 생성자를 만들어줍니다.
이제 test2를 new 연산자로 객체를 생성하게 되면 test1, test2의 속성과 메소드를 사용할 수 있게 됩니다.
계속해서 객체를 확장하고 싶다면 test3이라는 새로운 객체 함수에 test2를 상속받고 프로토타입 객체를 설정하고 생성자를 만들어주시면 됩니다.
이런 방식으로 객체를 계속해서 상속, 확장할 수 있습니다.
3. 메소드 속성의 옵션 부여
var obj = {
a : 10,
b : 20
};
const test = Object.create(obj, {
a : {
value: 30,
writeable: false,
configurable: false
}
});
Object.create 메소드로 객체를 생성 시에 속성의 value, writeable, configurable을 설정할 수 있습니다.
writeable 값이 false이면 수정을 할 수 없는 readOnly가 됩니다.
configurable 값이 false이면 해당 속성을 삭제할 수 없게 됩니다. 즉, delete test.a로 해당 속성을 지울 수 없습니다.
https://velog.io/@thms200/Object.create-
https://www.zerocho.com/category/JavaScript/post/573d812680f0b9102dc370b7
'javaScript' 카테고리의 다른 글
javaScript - 비동기 함수 동기식으로 실행하기(Promise와 async) (0) | 2021.07.12 |
---|---|
javaScript - 스프레드 오퍼레이터(Spread Operator) (0) | 2021.07.12 |
javaScript - 유용한 메소드 모음 (0) | 2021.07.07 |
javaScript - 객체 생성 class (0) | 2021.07.05 |
javaScript - 프로토타입(prototype) 객체 (0) | 2021.06.29 |
댓글