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. 신시내티
    저는 여기 링크보고 완전히 이해가 되더라고요. 참고해 보시고 도움되시길 바래요.
    http://insanehong.kr......pe/
    대화보기
    • babyrice
      하하
      갓 배우고 있는 초보자라 아직 이해가 안가네요
      공부해서 다시보면 이해가 되겠지요
      답변 감사합니다.
      대화보기
      • 신시내티
        객체생성함수 바깥에서!! 자녀 함수(programmer) 가 새로운 method(coding) 를 추가로 갖기 위해서는 prototype을 붙여주어야 합니다.

        Programmer.coding <- 얘는 마치 객체함수 안에서!! 메소드를 이미 부여받고 나온 아이처럼 보이는데, 코드 상으론 그런 적이 없으니까 오류가 뜹니다.

        객체함수 안에서!! 받은 프로퍼티나 메소드는 부모로 부터 받은 유전 같은 거고
        객체함수 밖에서!! 받은 프로퍼티나 메소드는 태어난 후에 받은 성형수술 같은건데, 그 성형수술을 받으려면 prototype이라는 객체가 필요해요. ㅎㅎㅎ
        대화보기
        • 신시내티
          상속과 프로토타입에서 엄청 헤맸는데, 이고잉님 덕분에 좀 알것 같아요. 감사합니다!
        • babyrice
          Programmer.prototype.coding은 Programmer가 Person에게서 상속받은 것이 아니라 새 속성을 추가한 것인데 왜 Programmer.coding으로 안쓰고 prototype을 붙인건가요?
          제 생각에 coding은 Programmer의 고유한 것이라 prototype이 없어도 되는 줄 알았는데 없애면 실행이 안되네요.
        • 이승우
          2017/08/07 완료
        • 이승우
          2017/08/07 2/3까지 완료
        • Seo Yun Seok Tudoistube
          부모객체의 prototype 과 상속받은 자식객체의 prototype 이 서로 다르다고 이해하면 되겠네요. 감사합니다^_____^!!!
        • crable
          감사합니다
        • prototype 프로퍼티를 호출해 메서드를 추가하는 방법은 이해가 안되는데 일반 생성자 프로퍼티를 객체에 추가하는 방법이 조금 이해안가네요
          이해가는것만 정리하면
          (객체).prototype.(프로퍼티명) = 프로퍼티, 메서드
          (자식객체).prototype = new (부모객체)();
        • 김소희
          잘봤습니다 !
        • 신입1
          두번째 질문에서는 상속하고자 하는 프로퍼티의 위치가 다릅니다.
          영상에 나온 방법대로 Person.prototype 객체에 introduce 프로퍼티를 추가한 경우는 내부적으로 Person.prototype에만 해당 프로퍼티가 존재하게 되지만, 질문하신 방법처럼 Person에 바로 Person.introduce 프로퍼티를 정의한다면, new Person() 으로 새로운 객체를 생성할 때 마다 그 생성된 객체에 intoruce 프로퍼티가 존재하게 됩니다. 그렇다면 Person을 상속하고자 하는 Programmer, Designer, Marketer, Planner 등 여러가지의 자식들은 100% 똑같은 introduce 프로퍼티를 사용함에도 불구하고 1차링크로 걸린(1차 프로토타입 체인) 객체마다 introduce 프로퍼티가 중복하여 존재하는 결과가 생기죠. 그래서 Person.prototype에 정의하는 겁니다.
          대화보기
          • 신입1
            감사합니다.

            1.부모생성자를 정의한 후, 그 프로토타입객체에다 상속해줄 프로퍼티들을 정의한다.
            2.자식생성자를 정의한 후, 그 프로토타입 프로퍼티로 부모생성자로 생성된 객체(인스턴스)를 지정한다.
            3.자식생성자로 새로운 객체를 만든다. 이 객체는 부모생성자의 프로토타입에 있는 프로퍼티들을 상속받는다.
          • 임지호
            상속 : 부모의 기능을 자식이 물려받는 것.
            - 코드의 중복이 줄어든다.
            - 상속법 : 자식객체.prototype = new 부모객체(); / 부모객체에서 프로퍼티들 정의할 때 prototype 붙여줌
            - 기능추가 역시 자식객체를 생성하고 prototype을 붙여서 프로퍼티를 정의함.
          • 폭스킴
            상속개념 설명하실 때,

            화살표를 자식에서 부모쪽으로 항상 그리시던데 이게 어떤 관습적인 의미가 있나요?

            제 고정관념에는 상속이니까 부모에서 자식 쪽으로 화살표를 그리는 게 더 당연해보여서요~^^
          • 굳이 'programer.prototype.coding' 이런식으로 coding이라는 메소드를 만들 필요가 있는건가요?

            이 coding이라는 메소드를 상속받을 자식이 없다면 그냥

            function Programmer(name){
            this.name = name;
            function coding(){
            return "hellow world";
            }
            이렇게 하면 되지 않나요?

            }

            혹시 맨 아래에 있는 예제에서
            document.write(person.coding); 이렇게 하면

            hellow world가 뜨나요?
          • 왈라비
            질문하나 할려고해요

            var p = new 함수();
            하게되면 p라는 이름을 붙인 함수객체로 함수의 성질을 바꿔준다.로 이해했어요.

            그리고
            programmer.prototype이 person함수객체로 만드는데
            이미 person함수는 프로토타입객체이기때문에
            프로그래머 프로토타입객체와 펄슨함수 프르토타입객체가 '합쳐진다?' 이렇게 이해가 되는데,
            실제로는 프로그래머함수프로토타입객체가 펄슨함수프로토타입객체에 종속되니까 이해가 잘안되네요

            이미 객체가 된 펄슨함수를 다시 programmer프로토타입객체로
            객체화시킨다는 개념이 이해가 잘 안되요
            만약에 펄슨함수를 다시 객체로 한다고해도, 좌항의 프로그래머프로토타입객체가
            person함수객체의 상위로 가지않고, 어떻게 하위개념으로 가서 종속되는건가요?
          • prototype
            prototype 개념을 먼저 배우고, 이걸 하면 더 이해가 빠를거같네요
          • 웅쓰
            감사합니다!
          • 완료!
            완료! 감사합니다~
          • 취준생1
            어렵네요 프로토타입 개념이..
          • Daehyeop Ko
            감사합니다! 이제 뭔가 본격적으로 javascript의 기능에 들어가는 것 같아요. 아직 확실히 이해되지는 않지만, 다시 반복해서 보면 이해가 될 것 같아요. 객체지향 부분 진짜 꼼꼼히 봐야겠어요
          • yihsang
            잘 들었습니다. 감사합니다.
          • 사람구실
            안녕하세요.

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

            늘 좋은 수업 감사합니다.

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

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

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

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

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

            물론 가독성은 떨어지겠지만
          • 박고잉
            이고잉이 본명이 아니셨을 줄이야 충격ㅠㅠ 이름 같다고 좋아했었는데 ㅠ
          • ot_nagne
            일단 정주행
            따라하면서 익숙해지기!!
          • 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)을 사용하기 위해서요
                        대화보기
                        버전 관리
                        egoing
                        현재 버전
                        선택 버전
                        graphittie 자세히 보기