자바스크립트에서 프로토타입과 생성자에 관해 질문 좀 ㅠ ㅠ

naddolki의 이미지

function con()
{
// do something
}

var obj = new con();
alert(obj.hasOwnProperty("constructor")); // false
alert(obj.__proto__.hasOwnProperty("constructor")); // true

위의 코드에서도 보여주듯이 . . .
con() 을 이용해 obj 객체를 생성하더라도 . .
constructor 프로퍼티는 . . .
obj 가 아닌 obj.__proto__ 에 생성되는 걸로 알고 있는데요 .
근데, 어떤 원리로 ... 왜 그렇게 되는 건지 궁금합니다 ㅜ ㅜ

다시 말해 . . .

생성자 con() 를 호출해 생성한 객체 obj 가 있다면 . . .
해당 객체 obj 를 생성하는 데 사용한 생성자 con() 의 정보는 . . .
생성된 객체 obj 내에 있는 게 . . . 논리적으로 맞지 않을까요 .
바꿔 말하면 . . .
obj 에는 생성자가 없기 때문에 . . .

function f1(){}
obj.__proto__ = new f1();

alert(obj.constructor); // function f1(){}

위의 코드에서처럼 . . .
obj 의 프로토타입 객체를 변경하면 . . .
obj 자체의 생성자를 알 수 없게 됩니다 .

따라서, 어째서 constructor 를 모든 객체에 포함시키질 않고 . . .
프로토타입 객체에만 포함시키는지 . . .
궁금합니다 .

참고로, 프로토타입을 이용한 상속에 대해서는 . . .
아래의 주소에 있는 문서로 공부를했습니다 .
http://mobicon.tistory.com/16

읽어주셔서 정말 감사드립니다 .
복 받으실 거에요 .

tpe4의 이미지

저도 정확히 알고 있지는 못합니다만 직관적으로 답변드리자면

function con() 이 선언되는 순간에 con.prototype에 con을 constructor로 가지고 있는 object를 생성하는 듯 합니다.
여기서 con.prototype이 아닌 new con() 으로 생성되는 객체가 constructor 속성을 가지는 것이 옳지 않냐고 질문을 하셨는데
prototype 상속을 사용하는 입장에서 굳이 그렇게 할 필요가 없습니다. 어차피 프로토타입에서 constructor을 참조할 수 있는데, 매 객체마다 constructor 속성을 할당해 주는 것은 메모리 낭비이니까요...
constructor 마저도 상속을 받는거죠.

http://dmitrysoshnikov.com/ecmascript/chapter-7-2-oop-ecmascript-implementation/#constructor
해당 문서를 참고하시면 도움이 될 것 같습니다.

익명 사용자의 이미지

의견 주셔서 감사합니다 .

"function con() 이 선언되는 순간에 ... 듯합니다" <= 이건 맞는 말씀이십니다 .

근데, 메모리 낭비인지 여부를 따지는 단계에 이르기 앞서 . .
굳이 프로토타입 객체에 constructor 을 둬야 할 이유가 있었느냐는 겁니다 .

외려, new_로_생성한객체.constructor 혹은 instanceof 연산자를 사용할 때 . . .
프로토타입 체인을 look up 해야 하기 때문에 . . . 부하가 가중될 수 있으니까요 .

논리적으로도 . . .
모든 객체는 . . .
생성하는 주체(사용자에 의해, 시스템에 의해)와 . . .
생성하는 방법(new와 생성자 함수를 이용하거나 객체 리터럴)에 대해 . . .
각각 자기 소유의 constructor 프로퍼티에 그와 관련된 정보를 기록하거나,
외부의 객체를 참조하는 게 맞지 않을까 . . . 조심스레 생각합니다 .

지금과 같이 프로토타입 객체에만 constructor 프로퍼티를 뒀을 땐 . . .
메모리가 절약된다는 잇점보다 논리 구조가 어그러진다는 단점이 더 문제가 된다고 생각합니다 . . .

예를 들어, 아래와 같은 상속 구조가 있다고 치죠 .

function GrandParents(){}

function Parents(){}
Parents.prototype = new GrandParents(); // 부모가 조부모를 상속

function Child(){}
Child.prototype = new Parents(); // 자식이 부모를 상속

var c = new Child(); // 자식은 function Child(){} 에 의해서 생성됨 .
alert(c.constructor); // 하지만 출력은 function GrandParents(){} .

c.constructor 는 . . .
프로토타입 체인을 구성하는 객체 노드들 가운데 . . .
new GrandParents() 로 생성한 객체 내의 constructor 가 유일하니까요 .
해당 constructor 프로퍼티가 참조하는 대상을 출력해주는 거죠 .

메모리 낭비의 문제이기에 앞서 . . .
논리적으로 이상한 것 같은데 . . .
저만 그렇게 느끼는 건지 ㅠ ㅠ

그리고, 이상한 점 하나를 더 말씀드리자면 . . . instanceof 연산자에 관한 건데요 .

c instanceof Child 는 . . .
c.constructor == Child 와 같이 풀어서 해석이 되는 걸로 배웠던 것 같은데 . . .

묘하게 . . .

alert(c instanceof Child); // true

이네요 .

말이 길어졌지만 . . .
여하튼 프로토타입과 생성자에 관해서는 뭔가 좀 복잡한 것 같네요 ;;
답변 주셔서 정말 감사합니다 .

자바 스크립트 완벽 가이드 원저자에게 메일을 보내볼 생각입니다 .

익명 사용자의 이미지

var c = new Child(); // 객체 c 는 function Child(){} 에 의해서 생성됨 .

tpe4의 이미지

저도 검색을 조금 해 보았는데 어째서 생성되는 객체가 아닌 프로토타입에 constructor를 두었냐에 대한 명쾌한 답은 찾기가 힘드네요.

다만 여러 문서에서 만약 생성자의 prototype을 변경한다면 constructor를 사용자가 직접 재지정 해주기를 권하고 있습니다.

var A = function() {};
A.prototype = new Object;
A.prototype.constructor = A;

이러한 형태로요. 이 패턴이라면 엉뚱한 constructor가 지정되는 경우는 없겠지만 좀 번거롭죠.
왜 굳이 이러한 방향으로 설계가 되었는지는... ECMAScript의 설계자들에게 물어봐야 할런지 ^^;
개인적으로는 constructor를 각 객체가 소유해야 하는가 또는 상속되어야 하는가의 관점의 차이라고 생각됩니다.

instanceof에 대해서는 제가 링크해드린 문서에 설명이 되어 있습니다.

if (foo instanceof Foo) {
...
}

it does not mean the check whether the object foo is created by the Foo constructor!

All the instanceof operator does is only takes the value of the Foo.prototype property and checks its presence in the prototype chain of foo, starting from the foo.[[Prototype]]. The instanceof operator is activated by the internal [[HasInstance]] method of the constructor.

foo의 프로토타입 체인에 Foo.prototype이 존재하는지만 검사한다고 하네요.

익명 사용자의 이미지

많은 도움이 되었습니다 .
복 받으실 거에요 .

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.