inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

코어 자바스크립트

prototype chaining 강의 예제로 만들어진 toString 작동원리(?) 설명 부탁드립니다

150

hgson.8

작성한 질문수 2

1

안녕하세요! 강의 4:23부터 나오는 toString method를 제대로 이해 못한 것 같아서 질문드립니다.. 

제가 이해한 바는 다음과 같습니다:
1. obj.toString()을 호출하면(실행시키면?) res 배열이 생성

2. obj의 각 프로퍼티 값에 대해 toString() 실행.

2.1.  a: 1의 경우 1이 객체가 아니므로 기존 toString() 메서드가 실행됨. res[0] = a: 1

2.2. b: {c: 'c'}의 경우

2.2.1. 값인 {c: 'c'}가 객체이므로 {c: 'c'}에 예제에서 만든toString() 자신이 다시 호출됨. {c: 'c'} 반환.

2.2.2 res[1] = b: {c: 'c'}

3. {res[0], res[1]} 반환

 질문드리고 싶은 내용은 다음과 같습니다:

1. 제가 잘못 이해하고 있는 부분이 있는 것 같아서 어떤 부분을 잘못 이해하고 있는지 알려주시면 감사하겠습니다ㅜ

확인차

var obj = {a: 1, b: 'c', d: {c: 'c'}} ;

Object.prototype.prac = function(){

var res = [];

for(var key in this){

    res.push(`${key}: ${typeof this[key]===

                'object'? this[key].prac(): this[key].toString()} 

            `);

       };

return '{'+res.join(', ')+'}';

}

로 예제를 바꿔서 실행해봤는데 반환값이

a: 1, b: c, d: {c: 'c' 로 마지막 프로퍼티 값에 뒷쪽 중괄호가 반환이 안되어서요, 

원리를 잘못 이해하고 예제를 바꿔서 이런 오류가 나는 게 아닌가 싶은 생각이 들었습니다.. 

중괄호가 반환되지 않는 이유도 함께 설명해주시면 감사하겠습니다..!

2. 윗 obj.prac() 반환값에 prac method가 포함되었습니다. 강의 예제와는 달리 method가 함께 반환된 이유를 알고 싶습니다.

강의 잘 들으면서 도움 많이 받고 있습니다! 답변 해주시길 기다리겠습니다..! 감사합니다!

javascript

답변 1

2

정재남

설명의 편의상 2번 먼저 답을 드리겠습니다.

내장된 prototype 메서드들은 모두 enumerable하지 않도록(열거대상에서 제외되도록) 설정되어 있습니다.
toString 역시 마찬가지입니다.
따라서 obj.toString()을 해도 prototype 내부 메서드들은 출력되지 않는 것이지요.
반면 prac 메서드는 prototype에 새롭게 추가된 메서드로 enumerable 속성은 default인 true로 설정된 상태입니다.
때문에 for in문에 의해 열거대상에 포함되게 됩니다.

1번의 경우, 아마도 2번과 연관이 있는 것이 아닐까 조심스럽게 추측해 봅니다.
객체가 아닌 a, b 프로퍼티의 값들 및 d 프로퍼티 내부 객체의 c 프로퍼티의 값을  출력할 때까지는
toString 메서드를 이용하니 문제가 없었다가,

d 객체의 열거대상에 포함되는 prac 프로퍼티를 출력하기 위해서 Object.prototype.prac 메서드를 실행하니,
이제는 프로토타입 체이닝을 타고 계속해서 prac 메서드를 출력하고자 하게 됩니다.

Object.prototype.prac
Object.prototype.__proto__.prac
Object.prototype.__proto__.__proto__.prac ...

이런 식으로, 논리적으로는 Object.prototype이 모든 객체의 최종점이긴 하지만
Object.prototype 역시도 객체이기 때문에, 여기에 다시 __proto__에 접근하고자 하면
똑같은 객체임에도 불구하고 접근이 됩니다!!

따라서 "d: {c: c," 이후에는 
(d: { c: c, prac: func(), prac: func(), prac: func(),  ... ) 같은 식으로 
prac 프로퍼티의 결과값들이 무한대로 출력되거나,
혹은 중간에 Maximum call stack error를 던져야 할 것 같은데,

아마도 크롬 브라우저에서는 이러한 무한한 접근을 자동으로 중단하고 넘기는 로직이 마련되어 있는 것 같네요.
'중단'했기 때문에 이후의 결과인 '}'는 출력되지 않고,
이후 문제 없는 다음 코드를 이어서 실행하도록 한 것 같습니다.

* 테스트삼아 사파리에서 돌려보니 prac의 결과가 두 번 출력되고 정상적으로 '}'가 출력되네요.
브라우저별로 prototype에 중복 접근하려는 시도에 대한 처리방식이 다른가 봅니다.

다음과 같이 prac을 enumerable하지 않도록 설정하시면 문제 없이 잘 출력되는 걸 확인하실 수 있습니다.

var obj = {a: 1, b: 'c', d: {c: 'c'}} ;

Object.defineProperty(Object.prototype, 'prac', {
    value: function(){
      var res = [];
      for(var key in this){
         res.push(`${key}: ${typeof this[key] === 'object' ? this[key].prac(): this[key].toString()}`);
      }
      return '{'+res.join(', ')+'}';
    },
    enumerable: false
})

obj.prac();

인스턴스에서 prototype 프로퍼티에 직접 접근해야하는 이유

0

59

1

setTimeout 에서 this

0

81

1

2강부터 영상이 나오지 않습니다.

0

175

1

자바스크립트 주석에 이상한 점이 있어서 문의드립니다.

0

219

2

return 문 안에 여러 함수가 존재하는 것이 이해되지 않습니다.

1

259

1

클래스 static 멤버

1

253

1

실행컨텍스트와 스택프레임

2

567

1

프로토타입으로 상속할때 브릿지 사용 이유

0

320

1

호이스팅 관련 질문

1

335

1

책 66p. 예제 3-2 질문입니다.

0

356

1

강의 내용 10:58 캡슐화 질문입니다.

1

399

1

강의 내용 5:10 질문입니다.

1

422

2

전역 공간에서의 this

0

426

2

18:31 addEventListener의 this

1

480

1

outerEnvironmentReference 질문

1

372

1

실행 컨텍스트와 클로저에 대해 질문드립니다.

1

448

1

Object.prototype.constructor의 [[prototype]] ?

1

658

1

함수를 값으로 할당할 때

2

457

1

15:54 'ddd' 사라지는 오류?

4

375

1

프로토타입 getPrototypeOf(instance).constructor(n,a) 질문입니다.

1

405

1

기본형/가변형 질문입니당

0

333

0

선생님 그러면 섹션 0만 봐도 무방한가요!?

0

336

1

Hoisting과 environmentRecord에 관한 질문입니다.

1

292

1

안녕하세요, 데이터 변경 질문입니다.

0

329

1