ES5 / ES6 의 계승

원형 체인
  • / / 의 관계
  • 모든 구조 함수 에는 원형 대상 이 있 고 원형 대상 은 구조 함 수 를 가리 키 는 지침 을 포함 하 며 인 스 턴 스 는 원형 대상 을 가리 키 는 지침 이 있다.
  • --(prototype)--> --(constructor)-->
  • --(new )--> --(constructor)-->
  • --(__proto__)-->

  • 어떤 대상 (인 스 턴 스) 의 특정한 속성 이나 방법 을 사용 하려 면 먼저 대상 내부 에서 이 속성 을 찾 습 니 다. 해당 대상 의 원형 instance.__proto__ 에서 찾 지 못 하면 __proto__ 이 체인 을 따라 위로 찾 습 니 다. Object.prototype 찾 을 때 까지
  • javascript 에 있 는 모든 대상 이 있 기 때문에 이 체인 에서 출발 할 수 있 습 니 다
  • 자 바스 크 립 트 의 계승 은 전통 적 인 대상 과 달리 유형 에 의 해 계승 되 는 것 이 아니 라 원형 체인 을 통 해 계승 되 는 것 이다
  • ES5 계승
  • 복사 식 계승 (깊 은 복사 로 계승)
  • 원형 식 계승
  • 단점: 원형 만 계승 할 수 있 는 방법
  • 구조 함수 로 계승
  • 단점: 인 스 턴 스 속성 만 계승 가능
  • 조합 식 계승
  • 단점: 어떤 상황 에서 도 두 번 의 구조 함 수 를 호출 합 니 다 (부모 클래스 인 스 턴 스 를 만 들 때 하위 구조 함수 에서 부모 클래스 구조 함 수 를 호출 하지 않 을 때)
  • 조합 기생 식 계승 (비교적 완벽 한 계승 이지 만 부류 의 정적 방법, 정적 속성 을 계승 할 수 없다)
  • function Parent() {}
    
    function Child() {
        //         
        Parent.call(this) //           this   
    }
    
    //         
    Child.prototype = Object.create(Parent.prototype)
    
    //         constructor   
    Child.prototype.constructor = Child 

    두 가지 주의 점:
  • Object.create(proto, [propertiesObject]) MDN
           ,                   __proto__
    
    Object.create(null) //             
                 
    
    js                  
    function createObject(P) {
        var F = function() {}
        F.prototype = P.prototype
        return new F()
    }
  • 왜 하위 원형 의 constructor 지향 을 수정 합 니까? 완 일 봉
          :
         prototype        constructor   ,        
         ,          constructor   ,     prototype   constructor   
    
               ,    
    var c = new C()
    c.constructor === Child // false
    Child.prototype.constructor === Child // false
    
    c.constructor === Parent // true
    Child.prototype.constructor === Parent // true
    
                (c         Child   ),          
  • ES6 계승
    ES6 의 계승 은 본질 적 으로 원형 체인 을 빌려 계승 을 실현 한다.
    //    class extends    
    class Parent {
        static sayAge() {
            return '18'
        }
          constructor(name) {
            this.name = 'name'
        }
    }
    
    class Child extends Parent {
        constructor(name, age) {
            /**
             *     constructor      super   ,          this   ,               
             *    super      this  ,new        
             * Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
             * 
             * ES5               this,             this    (Parent.call(this))
             * ES6                  ,   this   (      super   ),            this
            */
            super(name, age)
              this.age = age
        }
    }
    //    :es6                    , ES5     
    //    extends   ,Child.__proto__ ==== Parent // true
    // Parent.__proto__    f() { [native code] }
    // Parent.__proto__.__proto__ === Object.prototype

    Babel 코드 바 뀐 ES6 계승 코드
    //      ,              
    "use strict";
    
    //           super   
    function _possibleConstructorReturn(self, call) {
      if (call && (_typeof(call) === "object" || typeof call === "function")) {
        return call;
      }
      return _assertThisInitialized(self);
    }
    
    function _assertThisInitialized(self) {
      if (self === void 0) {
        throw new ReferenceError(
          "this hasn't been initialised - super() hasn't been called"
        );
      }
      return self;
    }
    
    //                 
    function _getPrototypeOf(o) {
      _getPrototypeOf = Object.setPrototypeOf
        ? Object.getPrototypeOf
        : function _getPrototypeOf(o) {
            return o.__proto__ || Object.getPrototypeOf(o);
          };
      return _getPrototypeOf(o);
    }
    
    //       
    function _inherits(subClass, superClass) {
      // ...
      //   es5       
      subClass.prototype = Object.create(superClass.prototype, {
        constructor: { 
            value: subClass, //    constructor   
            writable: true, 
            configurable: true 
        }
      });
      //                 :Child.__proto__ = Parent
      //    (         )      prototype = Parent,                 
      if (superClass) _setPrototypeOf(subClass, superClass);
    }
    
    function _setPrototypeOf(o, p) {
      _setPrototypeOf =
        Object.setPrototypeOf ||
        function _setPrototypeOf(o, p) {
          o.__proto__ = p;
          return o;
        };
      return _setPrototypeOf(o, p);
    }
    
    // ...             
    
    var Parent =
      /*#__PURE__*/
      (function() {
        _createClass(Parent, null, [
          {
            key: "sayAge",
            value: function sayAge() {
              return "18";
            }
          }
        ]);
    
        function Parent(name) {
          _classCallCheck(this, Parent);
    
          this.name = "name";
        }
    
        return Parent;
      })();
    
    var Child =
      /*#__PURE__*/
      (function(_Parent) {
        _inherits(Child, _Parent);
    
        function Child(name, age) {
          var _this;
    
          _classCallCheck(this, Child);
          
          //            super    ,      super       this
          _this = _possibleConstructorReturn(this, _getPrototypeOf(Child).call(this, name, age));
    
          /***
            *          super         
            * _this.age = age;
            * return _possibleConstructorReturn(_this);
            *        super       this,         
            *
            *         _this.age = age
            *       _assertThisInitialized   ,    ,     super   
          */
    
          _this.age = age;
          return _this;
        }
    
        return Child;
      })(Parent);
    
    var c = new Child();
    
    //      babel  ,         ,   super,      babel           
    //       : Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
    
  • 원생 구조 함 수 는 extends 을 통 해 ES6 완 일 봉
  • 계승 을 실현 할 수 없다.
  • 자 류 는 원생 부류 내부 의 대상 을 받 지 못 하기 때문에 통과 call 도 안 된다
  • new 연산 자
    위 에서 계승 이 라 고 말 했 는데, 그것 은 실례 가 되 는 조작 부호 이다new 무슨 원리 예요?
    var obj = {}
    obj.__proto__ = Child.prototype
    F.call(obj)
    
    // 1.        
    // 2.         __proto__             prototype      ==>         
    // 3.        this        obj(  ),               ===>         

    원형 체인 과 관련 된 몇 가지 방법
  • hasOwnProperty: 이 방법 은 대상 자체 에 어떤 속성 이 있 는 지 찾 을 수 있 을 뿐 원형 체인 에서 찾 지 않 습 니 다
  • A.isPropertyOf(instanceA): A 가 인 스 턴 스 A 의 원형 대상 인지 아 닌 지 판단
  • instanceof: 대상 이 특정한 구조 함수 인지 아 닌 지 를 판단 하 는 실례
  • __proto__ 브 라 우 저 업 체 의 개인 적 인 실현 일 뿐 규범 은 지원 되 지 않 습 니 다. 규범 지원 Object.getPrototypeOf Object.setPrototypeOf
  • 좋은 웹페이지 즐겨찾기