Shin-Yeonghwa / Core_JS

Core_JS
2 stars 0 forks source link

7.3 클래스 상속 #23

Open KimHyeSeon opened 4 years ago

KimHyeSeon commented 4 years ago

study 완료 후 체크 부탁드립니다.

Lee-Bom commented 4 years ago

7-3 클래스 상속 7-3-1 기본 구현 프로토타입 체인을 활용해 클래스 상속 구현, 클래스와 비슷한 형태로 구현 클래스에 있는 값이 인스턴스의 동작에 영향을 줘서는 안됨 구체적인 데이터를 지니지 않고 오직 인스턴스가 사용할 메서드만을 지니는 틀로 작용하게끔!

var Rectangle = function (width, height) {
  this.width = width;
  this.height = height;
};
Rectangle.prototype.getArea = function () {
  return this.width * this.height;
};
var rect = new Rectangle(3, 4);
console.log(rect.getArea()); //12

var Square = function (width) {
  this.width = width;
};
Square.prototype.getArea = function () {
  return this.width * this.width;
};
var sq  = new Square(5);
console.log(sq.getArea()); //25

▼ Square에서 getArea를 Rectangle와 동일하게 적용하도록 변경
var Square = function (width) {
  this.width = width;
  this.height = width;
};
//getArea 메서드는 동일한 작용을 하므로 상위 클래스(Rectangle)에서만 정의
//하위 클래스(Square)에선 해당 메서드 상속하면서 height대신 width 넣어주면 됨
Square.prototype.getArea = function () {
  return this.width * this.height;
};

▼
var Square = function (width) {
  Rectangle.call(this, width, width);
};
Square.prototype = new Rectangle();

7-3-2 클래스가 구체적인 데이터를 지니지 않게 하는 방법

  1. 일단 만들고 나서 프로퍼티들을 일일이 지우고 더는 새로운 프로퍼티를 추가할수 없게 하기
  2. subClass의 prototype에 직접 superClass의 인스턴스 할당하는 대신, 아무런 프로퍼티를 생성하지 않는 빈 생성자 함수(Bridge)를 하나 더 만들어 그 prototype이 superClass의 prototype을 바라보게 한 후, subClass의 prototype에는 Bridge의 인스턴스를 할당
    var Rectangle = function (width, height) {
    this.width = width;
    this.height = height;
    };
    Rectangle.prototype.getArea = function () {
    return this.width * this.height;
    };
    var Square = function (width) {
    Rectangle.call(this, width, width);
    };
    var Bridge = function () {}; //빈 함수 추가
    Bridge.prototype = Rectangle.prototype; //빈 함수가 Rectangle.prototype 참조
    Square.prototype = new Bridge(); //Square에 Bridge 할당하면 Bridge자리에 Rectangle인 셈
    object.freeze(Square.prototype);
  3. ES5에서 도입된 object.create를 이용한 방법 subClass의 prototype의 proto가 superClass의 prototype을 바라보되, superClass의 인스턴스가 되지 않음
    //(...생략)
    Square.prototype = object.create(Rectangle.prototype); //Square: subClass, Rectangle: superClass
    Object.freeze(Square.prototype);
    //(...생략)

7-3-3 constructor 복구하기

OHKuenYoung commented 4 years ago

클래스 상속

1. 기본 구현

var Grade = function () {
    var args = Array.prototype.slice.call(arguments);

    for (var i = 0; i < args.length; i++) {
        this[i] = args[i];
    }
    this.length = args.length;
};

Grade.prototype = ['a','b','c','d'];
var g = new Grade(100, 80);

g.push(90);

console.log(g) // grade (0:100, 1:80, 2:90, length: 3);

delete g.length;
g.push(70);
console.log(g); // Grade {0:100, 1:80, 2:90, __ 4:70, length: 5}

클래스 값이 인스턴스의 영향을 줘서는 안된다.

2. 클래스가 구체적인 데이터를 지니지 않게 하는 방법

  1. 만들고 나서 프로퍼티들을 일일이 지우고 더는 새로운 프로퍼티를 추가할 수 없게 하는 방법

인스턴스 생성 후 프로퍼티 제거

var extendClass1 = function(SuperClass, SubClass, subMethods) {
    SubClass.prototype = new SuperClass();

    for (var prop in SubClass.prototype) {
        if (SubClass.prototype.hasOwnproperty(prop)) {
            delete SubClass.prototype[prop];
        }
    }

    if (subMethods) {
        for (var method in subMethods) {
            SubClass.prototype[method] = subMethods[method];
        }
    }

    Object.freeze(SubClass.prototype);
    return SubClass;
}

var Square = extendClass1(Rectangle, function (width) {
    Rectangle.call(this,width, width);
})

2.SubClass의 prototype에 직접ㅂ SuperClass의 인스턴스를 할당하는 대신 아무런 프로퍼티를 생성하지 않는 빈 생성자 함수를 하나 더 만들어서 그 prototype을 바라보게끔 한 다음, SubClass의 prototype에는 Bridge의 인스턴스를 할당 하는 것

클래스 상송 및 추상화 방법 - 빈함수를 활용

var extendClass2 = (function (){
    var Bridge = function() {};

    return function (SuperClass, SubClass, subMethods) {
        Bridge.prototype = SubClass.prototype;
        SubClass.prototype = new Bridge();

        if (subMethods) {
            for(var method in subMethods) {
                SubClass.prototype[method] = subMethods[method];
            }
        }
        Object.freeze(SuperClass.prototype);
        return SubClass;
    }
})();

3.Object.cteate 를 이용한 방법 (가장 간단하면서도 안전하다)

Square.prototype = Object.create(Rectangle.prototype);
Object.freeze(Square.prototype)

3.constructor 복구하기

위 세가지 방법으로 상속에는 성공했지만 constructor은 여전히 SuperClass를 가리키는 상태이다. 위 코드들의 SubClass.prototype.constructor가 원래의 sub class 를 바라보도록 해주면 된다.

var extendClass1 = function(SuperClass, SubClass, subMethods) {
    SubClass.prototype = new SuperClass();

    for (var prop in SubClass.prototype) {
        if (SubClass.prototype.hasOwnproperty(prop)) {
            delete SubClass.prototype[prop];
        }
    }

    SubClass.prototype.constructor = SubClass; // 추가

    if (subMethods) {
        for (var method in subMethods) {
            SubClass.prototype[method] = subMethods[method];
        }
    }

    Object.freeze(SubClass.prototype);
    return SubClass;
}

2.

var extendClass2 = (function (){
    var Bridge = function() {};

    return function (SuperClass, SubClass, subMethods) {
        Bridge.prototype = SubClass.prototype;
        SubClass.prototype = new Bridge();
        SubClass.prototype.constructor = SubClass;//추가
        Bridge.prototype.constructor = SuperClass; //추가

        if (subMethods) {
            for(var method in subMethods) {
                SubClass.prototype[method] = subMethods[method];
            }
        }
        Object.freeze(SuperClass.prototype);
        return SubClass;
    }
})();

3.

var extendClass3 = function(SuperClass, SubClass, subMethods) {
    SubClass.prototype = Object.create(Rectangle.prototype);

    SubClass.prototype.constructor =SubClass; //추가

    if (subMethods) {
        for (var method in subMethods) {
            SubClass.prototype[method] = subMethods[method];
        }
    }

    Object.freeze(SubClass.prototype);
    return SubClass;
}
eunzy38 commented 4 years ago

클래스 상속

1. 기본 구현

var Rectangle = function (width, height) {
  this.width = width;
  this.height = height;
};
Rectangle.prototype.getArea = function () {
  return this.width * this.height;
};
var rect = new Rectangle(3, 4);
console.log(rect.getArea());      // 12

var Square = function (width) {
  this.width = width;
};
Square.prototype.getArea = function () {
  return this.width * this.width;
};
var sq  = new Square(5);
console.log(sq.getArea());       // 25


Square.prototype.getArea = function () { return this.width * this.height; };

<br>

- getArea 메서드는 동일한 작용을 하므로 상위 클래스(Rectangle)에서만 정의
- 하위 클래스(Square)에선 해당 메서드 상속하면서 height대신 width 넣어주면 됨
```javascript
var Square = function (width) {
  Rectangle.call(this, width, width);
};
Square.prototype = new Rectangle();

2. 클래스가 구체적인 데이터를 지니지 않게 하는 방법

1. 만들고 나서 프로퍼티들을 일일이 지우고 더는 새로운 프로퍼티를 추가할 수 없게 하는 방법

인스턴스 생성 후 프로퍼티 제거
var extendClass1 = function(SuperClass, SubClass, subMethods) {
    SubClass.prototype = new SuperClass();

    for (var prop in SubClass.prototype) {
        if (SubClass.prototype.hasOwnproperty(prop)) {
            delete SubClass.prototype[prop];
        }
    }

    if (subMethods) {
        for (var method in subMethods) {
            SubClass.prototype[method] = subMethods[method];
        }
    }

    Object.freeze(SubClass.prototype);
    return SubClass;
}

var Square = extendClass1(Rectangle, function (width) {
    Rectangle.call(this,width, width);
})

2. SubClass의 prototype에 직접 SuperClass의 인스턴스를 할당하는 대신 아무런 프로퍼티를 생성하지 않는 빈 생성자 함수를 하나 더 만들어서 그 prototype을 바라보게끔 한 다음, SubClass의 prototype에는 Bridge의 인스턴스를 할당 하는 것

빈함수 활용
var extendClass2 = (function (){
    var Bridge = function() {};

    return function (SuperClass, SubClass, subMethods) {
        Bridge.prototype = SubClass.prototype;
        SubClass.prototype = new Bridge();

        if (subMethods) {
            for(var method in subMethods) {
                SubClass.prototype[method] = subMethods[method];
            }
        }
        Object.freeze(SuperClass.prototype);
        return SubClass;
    }
})();

3. Object.cteate 를 이용한 방법 (가장 간단하고 안전하다)

Object.create 활용
Square.prototype = Object.create(Rectangle.prototype);
Object.freeze(Square.prototype)

3. constructor 복구하기

인스턴스 생성 후 프로퍼티 제거
var extendClass1 = function (SuperClass, SubClass, subMethods) {
  SubClass.prototype = new SuperClass();
  for (var prop in SubClass.prototype) P{
    if (SubClass.prototype.hasOwnProperty(prop)) {
      delete SubClass.prototype[prop];
    }
  }
  SubClass.prototype.constructor = SubClass;
  if (subMethods) {
    for(var method in subMethods) {
      SubClass.prototype[method] = subMethods[method];
    }
  }
  Object.freeze(SubClass.prototype);
  retrun SubClass;
};
빈 함수 활용
var extendClass2 = (function () {
  var Bridge = function () P{;
  return function (SuperClass, SubClass, subMethods) {
    Bridge.prototype = SuperClass.prototype;
    SubClass.prototype = new Bridge();
    SubClass.prototype.constructor = SubClass;
    Bridge.prototype.constructor = SuperClass; //SubClass.prototype이 SuperClass 바라보도록!
    if (subMethods) {
      for (var method in subMethods) {
        SubClass.prototype[method] = subMethods[method];
      }
    }
    Object.freeze(SubClass.prototype);
    return SubClass;
  };
})
Object.create 활용
var extendClass3 = function (SuperClass, SubClass, subMethods){
  SubClass.prototype = Object.create(SuperClass.prototype);
  SubClass.prototype.constructor = SubClass;
  if (subMethods) {
    for (var method in subMethods) {
      SubClass.prototype[method] = subMethods[method[;
    }
  }
  Object.freeze(SubClass.prototype);
   return SubClass;
};