본문 바로가기
JavaScript

[js] 자바스크립트 DeepDive 19장 (11) ~ (14) 요약

by Delants 2023. 3. 24.

* 본 내용은 자바스크립트 DeepDive 내용을 참고하여 정리한 것입니다.

 

19장. 프로토타입 (11) ~ (14)

 

11. 직접 상속 (p.299 ~ 302)

● 11.1) Object.create에 의한 상속

- object.create메소드는 명시적으로 프로토타입을 지정하여 새로운 객체를 생성한다.

- object.create메소드도 다른 객체 생성 방식과 마찬가지로 추상 연산 OrdinaryObjectCreate를 호출함 

 

● object Create의 메소드

- 첫 번째 매개변수: 생성할 객체의 프로토타입으로 지정할 객체를 전달

- 두 번째 매개변수: 생성할 객체의 프로퍼티 키와 프로퍼티 디스크립터 객체로 이뤄진 객체를 전달 (생략가능)

 

// 지정된 프로토타입 및 프로퍼티를 갖는 새로운 객체를 생성하여 반환한다.
@param {Object} prototype // 생성할 객체의 프로토타입으로 지정할 객체
@param {Object} [propertiesObject] // 생성할 객체의 프로퍼티를 갖는 객체
@returns {Object} // 지정된 프로토타입 및 프로퍼티를 갖는 새로운 객체

Object.create(prototype[,propertiesObject])

 

- eslint에서는 Object.prototype메소드를 통해 프로토타입 체인의 종점에 위치하는 객체를 생성할 수 있으므로, 직접 호출 방식은 권장하지 않음.

- 따라서 이 경우에는 간접 호출 방식이 필요

// 19-54 간접호출방식
const nums = Object.create(null);
nums.a = 1;
console.log(Object.prototype.hasOwnProperty.call(nums, 'a')) // true

 

 

● object Create의 메소드의 장점

- new연산자가 없어도 객체 생성 가능

- 프로토타입을 지정하면서 객체 생성 가능

- 객체 리터럴에 의해 생성된 객체도 상속 가능

- Object.prototype의 빌트인 메소드인 Object.prototype.hasownproperty, Object.prototype.isprototypeof, Object.prototype.propertyIsEnumerable 등은 모든 객체의 프로토타입의 종점(Object.prototype)의 메소드므로 모든 객체가 상속받아 호출 가능하다. (직접 호출 방식)

 

//19-52 Object.prototype의 빌트인 메소드를 직접 호출하기
 const nums = {a:1};
 console.log(nums.hasOwnProperty('a')); // true

 

 

● 11.2) 객체 리터럴 내부에서 __proto__에 의한 직접 상속

- ES6에서는 객체 리터럴 내부에서 __proto 접근자 프로퍼티를 사용하여 직접 상속 구현 가능.

// 19-55 __proto__에 의한 직접 상속
const myproto = {a:100}
const nums = {
    b: 50,
    __proto__: myproto // 객체를 직접 상속받는다.
};
console.log(nums.a,nums.b); // 100 50
console.log(nums.a * nums.b); // 5000
console.log(Object.getPrototypeOf(nums) === myproto); // true

 

 

12. 정적 프로퍼티/메소드 (p.303 ~ 306)

 

● 정적 프로퍼티/메소드의 개념

- 생성자 함수로 인스턴스를 생성하지 않아도 참조/호출할 수 있는 프로퍼티 혹은 메소드를 말함.

- 정적 프로퍼티/메소드는 인스턴스의 프로토타입 체인에 속한 객체의 프로퍼티/메소드가 아니므로, 생성자 함수가 생성한 인스턴스로 참조/호출할 수 없다.

- 하지만, object.prototype.hasOwnProperty메소드는 object.prototype(체인의 종점)의 메소드이므로 호출할 수 있다.

- 프로토타입/메소드 표기 시 prototype을 #으로 표기하는 경우도 있다.

 

● 예제로 확인하는 정적 프로퍼티/메소드

// 19-56 정적 프로퍼티 메소드

// 생성자 함수 만들기
function person(name) {
    this.name = name;
}

// 프로토타입 메소드 만들기
person.prototype.say = function () {
    console.log(`my name is ${this.name}`);
};

// 정적 프로퍼티
person.staticprop = 'static propr';

// 정적 메소드
person.staticMethod = function () {
    console.log('staticMethod');
};

const me = new person('kim');

// 생성자 함수에 추가한 정적 프로퍼티/메소드는 생성자 함수로 참조 및 호출함
person.staticMethod(); // staticMethod

// 그리고, 생성자 함수가 생성한 인스턴스로는 참조 및 호출 불가함
me.staticMethod(); // TypeError: me.staticMethod is not a function

- person생성자 함수는 객체이므로, 자신의 프로퍼티/메소드를 소유할 수 있다.

- person생성자 함수 객체가 소유한 프로퍼티 / 메소드를 정적 프로퍼티/메소드라고 한다.

 

 

13. 프로퍼티 존재 확인 (p.306 ~ 307)

 

● in연산자

- in연산자는 객체 내 특정 프로퍼티가 존재하는지의 여부를 확인한다.

 

// 19-59 in연산자

const region = {
    name : 'busan',
    popu : 340
};

console.log('name' in region); // region객체에 name프로퍼티가 존재하므로 true
console.log('popu' in region); // region객체에 popu프로퍼티가 존재하므로 true
console.log('mayor' in region); // region객체에 mayor프로퍼티가 존재하지 않으므로 false

 

- in연산자는 확인 대상 객체가 상속 받은 모든 프로토타입의 프로퍼티를 확인하므로 주의한다. 즉, object.prototype의 메소드인 tostring프로퍼티를 검색한다면 true로 표시될 것이다.

- ES6에서는 in연산자 대신 Reflect.has 메소드를 사용할 수도 있다.

 

 

● Object.prototype.hasOwnProperty 메소드

- Object.prototype.hasOwnProperty메소드를 사용해서 객체에 특정 프로퍼티의 존재 여부를 확인할 수 있다.

- 객체 고유의 프로퍼티 키인 경우에만 true반환, 상속받은 프로퍼티 키일 경우 false를 반환한다.

// 19-62 hasOwnProperty

const region = {
    name : 'busan',
    popu : 340
};
console.log(region.hasOwnProperty('name')); // true
console.log(region.hasOwnProperty('tostring')); // false

 

 

14. 프로퍼티 열거 (p.307 ~ 312)

 

● 14.1) for..in문

- 기본문법은 for (변수선언문 in 객체) {...} 와 같은 형태

- in연산자처럼 순회 대상 객체 뿐만 아니라, 상속받은 프로토타입의 프로퍼티까지 열거한다.

- 다만, 객체의 모든 프로퍼티 중 프로퍼티 어트리뷰트 [[Enumerable]]의 값이 true인 경우인 프로퍼티를 순회하여 열거한다. 아래 예제를 참고해 주세요.

- 객체의 프로퍼티 개수만큼 순회하며 for~in문의 변수 선언문에서 선언한 변수에 프로퍼티 키를 할당함.

- 프로퍼티 키가 심벌인 프로퍼티는 열거하지 않는다.

 

// 19-65, 66

const region = {
    name : 'busan',
    popu : 340
};

// in연산자 사용
console.log('toString' in region); // TRUE

// for~in구문 사용
for (const key in region) {
    console.log(key + ': ' + region[key]);
}
console.log(Object.getOwnPropertyDescriptor(Object.prototype, 'toString')); 

/* 결과값
true
name: busan
popu: 340
{
  value: [Function: toString],
  writable: true,
  enumerable: false,
  configurable: true
}
*/

 

- 객체 자신의 프로퍼티만 열거하려면, 다음과 같이 Object.prototype.hasOwnProperty메소드를 사용하여 자신의 프로퍼티인지 확인해야 한다.

// 19-69 
const region = {
    name : 'busan',
    popu : 340,
    __proto__: {mayor: 'park'}
};
for (const key in region) {
    if(!region.hasOwnProperty(key)) continue; // 객체 자신의 프로퍼티가 맞는지 확인
    console.log(key + ': ' + region[key]);
}

 

- for~in문은 프로퍼티 열거 시 순서를 보장하지 않는다. 그러므로 배열의 경우, 일반적인 반복문 for문이나, for..of문(34.3절), Array.Prototype.forEach메소드(27.9절)를 사용하는 것이 좋다.

 

 

● 14.2.1) Object.keys 메소드

- for..in문에서 객체 고유 프로퍼티 열거하기 위해서는 복잡한 과정이 요구된다.

- 그러므로 객체 고유 프로퍼티만 열거하기 위해서는 Object.keys/values/entries메소드를 사용하는 것이 좋다.

- Object.keys 메소드는 객체 자신의 열거 가능한 프로퍼티 키를 배열로 반환한다.

 

// 19-72 Object.keys 메소드의 사용
const region = {
    name : 'busan',
    popu : 340,
    __proto__: {mayor: 'park'}
};
console.log(Object.keys(region)); // [ 'name', 'popu' ]

 

 

● 14.2.2) Object.values 메소드

- ES8에서 도입

- Object.values메소드는 객체 자신의 열거 가능한 프로퍼티 값을 배열로 반환함

// 19-73 Object.values 메소드의 사용
const region = {
    name : 'busan',
    popu : 340,
    __proto__: {mayor: 'park'}
};
console.log(Object.values(region)); // [ 'busan', 340 ]

 

 

● 14.2.3) Object.entries 메소드

- ES8에서 도입

- Object.entries메소드는 객체 자신의 열거 가능한 프로퍼티 키와 값의 쌍의 배열을 반환한다.

// 19-74 Object.entries 메소드의 사용
const region = {
    name : 'busan',
    popu : 340,
    __proto__: {mayor: 'park'}
};
console.log(Object.entries(region)); // [ [ 'name', 'busan' ], [ 'popu', 340 ] ]

 

 

끝.

 

감사합니다.

댓글