JavaScript

상속

상속(inheritance)이란?

객체는 연관된 로직들로 이루어진 작은 프로그램이라고 할 수 있다. 상속은 객체의 로직을 그대로 물려 받는 또 다른 객체를 만들 수 있는 기능을 의미한다. 단순히 물려받는 것이라면 의미가 없을 것이다. 기존의 로직을 수정하고 변경해서 파생된 새로운 객체를 만들 수 있게 해준다. 

아래 코드는 이전 시간에 살펴본 코드다.

function Person(name){
    this.name = name;
	this.introduce = function(){
		return 'My name is '+this.name;	
	}	
}
var p1 = new Person('egoing');
document.write(p1.introduce()+"<br />");

결과

My name is egoing

위의 코드를 아래와 같이 바꿔보자.

function Person(name){
    this.name = name;
}
Person.prototype.name=null;
Person.prototype.introduce = function(){
	return 'My name is '+this.name;	
}
var p1 = new Person('egoing');
document.write(p1.introduce()+"<br />");

결과는 같다. 하지만 상속을 위한 기본적인 준비를 마쳤다. 이제 상속을 해보자.

function Person(name){
    this.name = name;
}
Person.prototype.name=null;
Person.prototype.introduce = function(){
	return 'My name is '+this.name;	
}

function Programmer(name){
	this.name = name;
}
Programmer.prototype = new Person();

var p1 = new Programmer('egoing');
document.write(p1.introduce()+"<br />");

Programmer이라는 생성자를 만들었다. 그리고 이 생성자의 prototype과 Person의 객체를 연결했더니 Programmer 객체도 메소드 introduce를 사용할 수 있게 되었다. 

Programmer가 Person의 기능을 상속하고 있는 것이다. 단순히 똑같은 기능을 갖게 되는 것이라면 상속의 의의는 사라질 것이다. 부모의 기능을 계승 발전할 수 있는 것이 상속의 가치다.

function Person(name){
    this.name = name;
}
Person.prototype.name=null;
Person.prototype.introduce = function(){
    return 'My name is '+this.name;	
}

function Programmer(name){
	this.name = name;
}
Programmer.prototype = new Person();
Programmer.prototype.coding = function(){
	return "hello world";
}

var p1 = new Programmer('egoing');
document.write(p1.introduce()+"<br />");
document.write(p1.coding()+"<br />");

결과

My name is egoing
hello world

Programmer는 Person의 기능을 가지고 있으면서 Person이 가지고 있지 않은 기능인 메소드 coding을 가지고 있다. 

prototype이 무엇인가 궁금할 것이다. 이번 시간은 상속에 대한 개념적인 부분만 살펴본 것이고 다음 시간에 prototype에 대한 구체적으로 알아보자.

댓글

댓글 본문
작성자
비밀번호
  1. 완료!
    완료! 감사합니다~
  2. prototype이 공유하는 객체라고 하면 이해가 가는데요.. 부모 자식간의 상속이라고 하니.. 왜 부모고 자식인지 잘 모르겠어요. Programmer.prototype = Person.prototype; 해도 결과는 같지 않나요?
  3. 취준생1
    어렵네요 프로토타입 개념이..
  4. Daehyeop Ko
    감사합니다! 이제 뭔가 본격적으로 javascript의 기능에 들어가는 것 같아요. 아직 확실히 이해되지는 않지만, 다시 반복해서 보면 이해가 될 것 같아요. 객체지향 부분 진짜 꼼꼼히 봐야겠어요
  5. yihsang
    잘 들었습니다. 감사합니다.
  6. 사람구실
    안녕하세요.

    프론트 엔드 엔지니어 공부를 하고 있는 학생입니다.

    늘 좋은 수업 감사합니다.

    혹시 Obj.create() 에 대한 내용이 최근(?) 추가되었던데 prototype을 활용하는 것과 어떻게 다른 것인지

    명확한 강의가 있으면 좋을 것 같습니다. 물론, 홀로 인터넷을 찾아보고 공부를 할 수도 있지만요,

    늘 감사드립니다. 선생님
  7. Harry S. Hur
    예제가 너무 와닿지가 않아서 잘 이해가 안가요 ㅠㅠ
  8. fasdgoc
    감사합니다
  9. tymmkang
    생성자 부분역시 재귀적으로 만들어서 더 깔끔하게 구현 할 수 있습니다.

    function Programmer(name){
    Person.call(this, name);
    }

    이렇게요 ㅎㅎ
  10. 이주환
    2016. 04. 25
    제가 생각하는 상속은
    어떠한 문서를 카피하는데 원본에 있는 내용을 모두 가져와서
    그것을 수정,삭제,보완했다고 했을 때 원본에는 그 어떠한 내용도 변경되지않고
    카피해온 내용만 변경하여 사용할 수 있는 것이라고 생각합니다.
    이해하는데 도움이 되셨길 바랍니다.
  11. JustStudy
    고맙습니다
  12. seroin
    상속의 개념은 사실상 확장에 더 가깝습니다.
    외국에서는 상속이라고 안하고 extends(확장) 의 개념을 더 사용하지요
    A라는 클래스에 있는 속성과 기능에 추가하여 B라는 클래스를 만든다면
    A를 확장하여 B를 만드는 것 입니다.
    이렇게 이해하는게 더 자연스러울 거라고 생각해요~
  13. terminater
    수업에서 이해가 잘 안되면 아래 댓글을 죽 훑어 보는 이유가 있는 것이죠.
  14. terminater
    대부분 스승은 배운지가 오래되어서 배울 때의 느낌을 잊어 버릴 수가 있어서 학생들에게 어떻게 가르쳐야 잘 이해할 수 있을지 모를 수도 있어요. 이 때 배운지 얼마 안된 선배가 설명하면 훨씬 이해가 잘 될 때가 있지요. jokerol 님의 상속에 관한 댓글이 금상첨화가 되는 이유입니다.
  15. terminater
    초보자들의 질문을 고수님들이 많이 참여해서 댓글을 달아 주시면 고맙겠네요. 선생님이 아무리 잘 설명을 해 주셔도 간혹 놓치는 부분이 있거나 빠뜨리는 부분이 있을 수 있겠죠. 또 이 정도는 학생들이 알고 있을거라 판단해서 설명하지 않는 부분도 존재할 거구요.
  16. 아이고잉
    이런짓을 왜 하는지 궁굼해지기 시작하네요^^
  17. 고고
    상속이 신기하게 되네요
    쉽다고 해야하나.....

    물론 가독성은 떨어지겠지만
  18. 박고잉
    이고잉이 본명이 아니셨을 줄이야 충격ㅠㅠ 이름 같다고 좋아했었는데 ㅠ
  19. ot_nagne
    일단 정주행
    따라하면서 익숙해지기!!
  20. yunye
    초보자의 개인적 풀이입니다. 위에서 person을 상속받은 모든 객체가 name이라는 매개변수를 사용하잖아요? person 생성자가 프로그래머 뿐만 아니라 다른 여러 객체에 상속을 해주는 경우를 생각해 보면, 만약 코드중에 person 함수 자체에서 name매개변수가 어떤 특정한 값을 같게 되는 맥락이 존재하면 다른 prototype체인으로 연결된 객체에도 영향을 주지 않을까 생각해봤습니다. 그래서 상속받았지만 다른 name값을 갖기 위해 한번 null로 초기화 해주는게 아닌가하구요. 구조는 체인으로 연결되어있지만, 값은 null을 이용해 체인을 끊어주는거 아닐까요?
    대화보기
    • jokerol
      음.. 상속이라는 기술이 나타나게 된 기원에 대해 설명을 드려야 할 것 같은데요.
      상속이라는 것은 근본적으로, 한번 만들어 놓은 기능을 다시 구현하지 않겠다는 의지의 표현입니다.
      한번 만들어 놓은 기능, 즉 코드를 다시 재사용 할 수 있는 가장 쉬운 방법이 무엇일까요?

      바로 코드 복사 입니다.
      1) A 라는 기능을 만들었는데 거기에 B 라는 기능을 추가하고 싶다면.
      2) A 코드를 복사해서, 거기에 B 기능 코드를 추가해 넣으면 됩니다.

      그런데, 이렇게 하면 B의 원시(소스)코드안에 A 코드가 중복되게 나타납니다. 이렇게 될 경우 나타나는 문제가

      1) 우리가 필요한 B 기능 외에 이미 존재하는 A 의 기능을 표현하기 위한 코드가 중복으로 들어가므로 코드 자체의 용량 증가.

      2) 나중에 A 코드 로직이 바뀌어서 수정해야 한다면, B 코드 안의 A 코드까지 수정해야 하는 문제. 만일, B 외에도 C, D, E 도 필요해 각자 A 코드를 복사해 가지고 있다면 이들을 모두 깔끔히 수정해야 하는 엄청난 문제 발생.

      등의 코드를 유지보수 하는데 많은 이슈가 생깁니다.

      그리하여, 사람들이 생각한 방법은.. '코드 복사를 인간에 맞기지 말고 언어 레벨에서 지원하도록 하자' 입니다.
      근본적으로 B 안에 A의 기능이 구현되려면, 코드 복사외에는 답이 없습니다만 이것을 사람들이 자의적으로 실제 원시(소스)코드 복사를 통해 이루던 것을, 컴퓨터에게 원본 파일이 있는 곳을 알려주고, 실제 실행될때 원본 코드를 복사해와서 내가 추가 구현한 B 기능 위에 복사해 넣도록 한것입니다.

      이것이 저희가 이해하기 쉽게 상속이라고 표현하는 기술의 내부 구현 컨셉입니다.
      컴퓨터는 스스로 (아직?) 생각 못하기 때문에, 사용자가 사용할 부모 기능의 범위등을 알수가 없습니다. 그리고 위에 설명했듯 기원 자체가 코드를 몽땅 복사(또는참조)해 오는 것이기 때문에(사용자가 필요한 것만 골라서 복사하기 보다는, 몽땅 복사하는것이 구현측면에서 훨씬 쉬우리라는것은 쉽게 이해가실겁니다).. 부모 기능 중 사용하기 원하지 않는 기능은 상속 받은 측에서 사용하지 않는 것으로 처리하면 되는 모습으로 최종 안착하게 된 것입니다.

      자바 스크립트가 스크립트 언어라서 큰 자유도를 제공한다고 알고는 있는데 상속까지도 골라서 받을수 있게 되어 있을지는.. 개인적으로 의문이긴합니다. 어쨋든 본 글이 상속이라는 것에 대해 이해하는데 도움이 되었으면 좋겠습니다.

      PS 밑에 Prototype 섹션을 보고 오니까.. 자바스크립트는 Prototype 이라는 예약 객체에 대한 대입을 통해 상속을 표현한거 같네요..
      대화보기
      • document.write
        function Person(name){
        this.name=name;
        }
        Person.prototype.name=null;
        Person.prototype.introduce=function(){
        return 'My name is '+this.name;
        }
        function Programmer(name){
        this.name=name;
        }
        Programmer.prototype=new Person();

        var p1=new Programmer('egoing');
        console.log(p1.introduce());
        My name is egoing
        undefined
        ------------------------------------------------------
        Programmer.prototype.name;
        undefined
        Programmer.prototype.introduce();
        "My name is undefined"
        -------------------------------------------------------
        Person.prototype.name;
        null
        Person.prototype.introduce();
        "My name is null"
        -------------------------------------------------------
        p1.name;
        "egoing"
        p1.introduce();
        "My name is egoing"
        -------------------------------------------------------
        콘솔창에서 각객체의 name과 introduce()를 호출하니까 값이 이렇게 나오네요
        p1--> Programmer-->Person 이렇게 연결되어서 Person의 introduce()를 사용하고 name 변수는 각객체마다
        서로 다른것 같네요
        대화보기
        • 플러스비 프리코
          필수는 아니지만 부모 클래스로 부터 물려받을 때 prototype의 constructor 프로퍼티를 현재 클래스로 변경해야 할 때도 있습니다.
          예시 상황: 내부 factory함수에서 내장 constructor 호출, 클래스의 이름을 가져오기 위해 constructor 프로퍼티를 사용할 경우 등.

          다음 링크를 참고하시기 바랍니다:
          http://stackoverflow.com......tor
        • 머머
          부모의 기능 중 부분만 물려받아야만 한다면 그 설계는 제대로 된 객체지향 설계가 아니지 싶어요.

          (근데 왠만한건 그냥 다 물려받고 필요없는 부분은 안쓰면 되지 않나요..?;;)

          //수정합니다 prototype으로 딩구르르님이 원하는 바를 이루실수 있을듯 합니다.
          대화보기
          • 머머
            저두 궁금합니다.

            null로 초기화 하지 않으면 name의 값은 undefined네요.

            제 생각에는 undefined보다 null을 주는게 의미상 명확한것 같아서 초기화한 것 같아요.

            더 보다보면 알겠죠?
            대화보기
            • 초보
              강의 잘 보고 있습니다. 처음 질문 올립니다.

              Person.prototype.name=null;

              이 부분을 왜 사용하는 것인지 궁금합니다..
              Programmer 객체에서 name을 선언해서 사용하고있는데,

              Person의 name 을 null 값으로 다시 선언해서 쓰는 이유가 궁금합니다.
            • 딩구르르
              항상 좋은 강의 감사드립니다. 이제 조금씩 정리가 되고 있어요.. 정말 너무 감사합니다.

              그런데 상속을 받을 때 부모의 것을 모두 받아야만 하는건가요?
              Programmer.prototype = new Person(); 이렇게 한다는 것은 부모의 것을 모두 받는 것 같은데
              예를 들어 부모의 것이 3개가 있고 2개만 물려 받고 싶을 때는 어떻게 해야 하나요?
              그리고
              function Person(name){
                 this.name = name;
                 this.introduce = function(){
                    return 'My name is '+this.name;
                 }
              }
              function Programmer(name){
                 this.name = name;
              }
              Programmer.prototype = new Person();
              var p1 = new Programmer('egoing');
              console.log(p1.introduce());
              이렇게 해도 상속이 되던데...
              위에서 prototype를 이해하기 쉽게 설명하기 위해 사용하신 것 같은데
              실제로는 둘 중에 어떤 방법으로 쓰나요?
              만약 이고잉님이 사용하신 방법으로 한다면
              Person.prototype.name=null;
              이 부분은 왜 추가를 하는 건가요?
            • egoing
              후자는 그냥 함수를 호출한거라서 그런 것 같습니다. 전자는 생성자 함수를 이용해서 객체를 만든거구요.
              대화보기
              • 어렵네
                2번에서 var p1 = new Programmer("egoing");
                에서 이해가 안되네요.

                바로 위에 Programmer.prototype = new Person();
                이라는 일 처리에서 상속이라고 강의를 봤는데

                var p1 = new Programmer("egoing");
                에서
                p2 = Programmer("egoing");
                라고 하면 안되는 이유가 뭔가요?

                p1일 경우는 확실히
                p1.introduce();
                를 상속 받던데
                p2일 경우는 상속을 받지 않은것 같아요.

                뭐가 틀려서 그런거죠?
              • 조신부리
                감사합니다
              • WebCat
                programmer라는 새 객체에 오리지널객체인 Person객체를 연결한거 아닌가요?
                Person의 속성(name, introduce)을 사용하기 위해서요
                대화보기
                • programmer.prototype= new Person();

                  이부분이요 변수에 클래스를 선언한건가요?..ㅜㅜ
                • 인혁
                  제 진짜 이름은 이고잉이 아닙니다 ㅋㅋㅋ 깨알같은 유머에요 ㅎㅎ
                • 샤핀
                  하.. 오늘은 javascript진도 다 때겠다고 마음 먹었건만 쉽지 않네요 ^^;;
                • 나무마루
                  감사합니다.
                • 타조알
                  친절하고 명쾌한 설명 감사드립니다.
                • 비니당
                  포로토타입이 뭔지 이제 이해가 좀 되네요 ^^
                • hehypapa
                  참 쉽게 잘설명해주시네요... 감사합니다..
                버전 관리
                egoing
                현재 버전
                선택 버전
                graphittie 자세히 보기