ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JS] 객체 지향 - 생성자와 new, 전역객체, this, 상속, prototype
    생활코딩/ 2020. 9. 5. 00:25

    [강의 출처] opentutorials.org/course/743/6584

     

    객체지향 - 생활코딩

    객체지향 프로그래밍은 크고 견고한 프로그램을 만들기 위한 노력의 산물이다. 객체지향이라는 큰 흐름은 현대적 프로그래밍 언어들을 지배하고 있는 가장 중요한 맥락이라고 할 수 있다. 하지

    opentutorials.org


    객체 지향 프로그래밍(Object Oriented Programming)

    -프로젝트가 확장되면서 기존의 절차적인 방법으로 정리하기 어려워질 때, 기능별로 로직을 구분해서 정리하는 방식 중 하나

    -해당 문법과 설계방식(문제의 복잡성을 적절히 단순화하여 설계하는 추상화(abstract)와 그룹핑, 캡슐화 등)을 아우르는 개념

    -JS는 Prototype-based Programming에 속함

     

    생성자(constructor)와 new

    -일반적으로 객체를 만드는 방법은 아래와 같다.

    var person = {
        'name' = 'a';
        'introduce' = function(){
            return 'My name is ' + this.name;
        }
    }
    document.write(person.introduce());
    

    -만약 person이라는 형식으로 객체를 여러 개 만들고 싶다면 생성자를 이용한다.

    -생성자(constructor)는 객체를 만드는 함수다. 자바스크립트에는 클래스가 없기 때문에 생성자는 객체와 독립적이다.

    function Person();       // 함수를 정의
    var p = new Person();    // 새로운 객체가 생성된다
    p.name = 'a';
    p.introduce = function(){
        return 'My name is ' + this.name;
    }
    

    -아래처럼 생성자로 쓰일 함수를 정의할 때, 필요한 로직(메소드와 프로퍼티 등)을 정의해두면 편리하게 객체를 생성할 수 있다.

     이런 작업을 초기화(initialize)라고 부른다.

    function Person(name){                      // 생성자로 쓰일 함수 정의
        this.name = name;
        this.introduce = function(){            // 여기서 메소드를 정의해두면
            return 'My name is ' + this.name;   // 이후 선언되는 객체들에서 반복적으로 사용가능
        }                                       // 이런 초기 세팅을 '초기화'라고 부름
    };
    var p1 = new Person('a');   // 생성자 Person에서 프로퍼티를 'a'로 정의
    var p2 = new Person('b');
    
    document.write(p1.introduce() + "<br />");
    document.write(p2.introduce() + "<br />");

     

    전역객체(Global Object)

    -자바스크립트의 모든 객체(전역변수 및 함수를 포함해서)는 window 객체의 프로퍼티다. [참고페이지]

    -node.js에서는 전역객체를 global라고 부른다.

    function func(){
        console.log('Hello?');
    };
    func();           // 'Hello?'
    window.func();    // 'Hello?'

     

    this

    -함수 내에서 함수를 호출한 맥락(context)의 객체를 가리킨다. this를 통해 함수와 객체를 연결시킬 수 있다.

    /* 별다른 맥락이 없는 경우, 전역객체인 window를 가리킨다 */
    
    function func(){
        if(window === this){
            console.log("window === this")
        }
    }
    func();        // window === this
    /* 객체에 소속된 메소드의 this는 그 객체를 가리킨다 */
    var o = {
        func: function(){
            if(o === this){
                console.log("o === this");
            }
        }
    }
    o.func();       // o === this

    -this는 객체 생성이 끝나서 어떤 식별자에 담기기 이전에도(객체 생성 진행 중에도) 해당 객체에 접근이 가능하다.

    /* 생성자 안에서 this는 생성될 객체를 가리킨다*/
    
    var funcThis = null;  // 다른 함수에서도 불러와야 하니까 일단 전역변수로 세팅
    
    function Func(){
        funcThis = this;  // 여기에서 this의 값으로 funcThis 재할당
    }
    var o1 = Func();              // new 없이 생성한 경우
    if(funcThis === window){      // 함수 Func() 맥락에서 그 함수의 객체는 window가 됨
        console.log('window');    // 'window'
    }                   
    var o2 = new Func();          // 생성자를 이용해 생성한 경우
    if(funcThis === o2){          // 호출한 시점에서 비어있는 {} 객체가 만들어지고, 그 객체가 생성자 내의 this
       console.log('o2');         // 'o2'
                    
                                 
    function Func(){
        console.log(o);
    }
    var o = new Func();          // undefined
                                 // 이 경우 호출이 모두 끝나야 var o가 할당완료되고, this가 o가 되는데,
                                 // 생성 중간에 o를 호출한 것이므로 아직 정의되지 않았다고 출력된다.

    -함수의 메소드 apply, call를 통해, 타 객체의 메소드를 적용 가능함

     *리터럴(literal)의 개념

    더보기

     new로 객체를 정의하지 않고 일반적인 방법으로 객체를 생성하는 경우 ~ 리터럴이라고 부른다

    // 함수 리터럴(function literal)
    function sum(x,y){
        return x+y;
    }
    
    // 객체 리터럴
    var o = { }
    var p = { }
    
    // 배열 리터럴
    var a = [1, 2, 3];
    
    var o = {}
    var p = {}
    function func(){
        switch(this){
            case o:
                console.log('o');
                break;
            case p:
                console.log('p');
                break;
            case window:
                console.log('window');
                break;
        }
    }
    
    func();           // 'window'
    func.apply(o);    // 'o'
    func.apply(p);    // 'p'
    /* apply가 사용된 맥락에 따라 window.func(), o.func(), p.func()처럼 해석됨 */

     

    상속(inheritance)

    -어떤 객체의 로직(메소드, 프로퍼티 등)을 prototype 객체를 통해 다른 객체에게 물려줄 수 있는 기능

    -상속을 통해 기존 객체로부터 새로운 파생 객체를 만들 수 있음

    function Person(name){
        this.name = name;
    }
    Person.prototype.name = null;               // 빌트인 메소드 prototype으로 프로퍼티 추가도 가능
    Person.prototype.introduce = function(){
        return 'My name is ' +this.name;
    }
    function Programmer(name){
        this.name = name;
    }
    Programmer.prototype = new Person();        // 이렇게 해서 Person의 로직을 상속 받음
    Programmer.prototype.coding = function(){   // 상속받은 부모 객체의 prototype을 복사
        return "hello world!";                  // coding()은 Programmer만 실행 가능한 메소드
    }
    
    function Designer(name){
        this.name = name;
    }
    Designer.prototype = new Person();
    Designer.prototype.design = function(){     // Designer의 고유 메소드를 구현
        return "beautiful!";
    }
    
    var p1 = new Programmer('a');
    console.log(p1.introduce());                // My name is a. Person의 메소드를 상속 받음
    console.log(p1.coding());                   // hello world!
    
    
    var p2 = new Designer('b');
    console.log(p2.introduce());                // My name is b. Person의 메소드를 상속 받음
    console.log(p2.design());                   // beautiful!
    console.log(p2.coding());                   // Designer 객체는 coding 프로퍼티가 없으므로 에러
                                       /* Uncaught TypeError: p2.coding is not a function */

     

    prototype

    -프로토타입 객체의 프로퍼티들은 생성자를 통해서 객체가 생성될 때 그 객체로 전달된다.

    -이렇게 프로토타입을 통해 프로퍼티들이 연결되는 형태를 'prototype chain'이라고 부른다.

    function Ultra(){}
    Ultra.prototype.ultraProp = true;
    
    function Super(){}
    Super.prototype = new Ultra();
    
    function Sub(){}
    Sub.prototype = new Super(); // 상속받고자하는 객체를 새로 생성해서 new() 형태로 전달해야함
                                 // Super.prototype()형태로 전달할 경우, Sub 객체의 변경사항이
    var o = new Sub();           // 부모인 Super 객체에도 영향을 줄 수 있기 때문
    console.log(o.ultraProp); // true

     

    댓글

Designed by Tistory.