arale 소스 코드 의 class 편 읽 기

업데이트: arale 소스 코드 의 attribute 편 읽 기
arale 은 아 리, 개원 지역사회 의 스타 인물 인 옥 백 입 니 다. 개발 한 구성 요소 입 니 다. 코드 가 상당히 아름 답 고 옥 백 의 개원 정신 을 칭찬 합 니 다. 저 는 당신 의 팬 입 니 다.
이 소스 코드 에 대한 깨 달 음 을 공유 합 니 다. 잘못된 부분 이 있 으 면 지적 해 주세요. = ̄ω ̄=
먼저 원형 에 기초 한 계승 에 대해 이야기 하 다.
먼저 segement fault 에서 토론 한 문 제 를 보 세 요.
function F() {}
Object.prototype.a = function() {}
Function.prototype.b = function() {}
var f = new F()
// F.a F.b f.a

F 는 a 와 b 를 호출 할 수 있 습 니 다. F 의 원형 체인 이 이 렇 기 때 문 입 니 다.(직관 적 해석: F 는 Function 인 스 턴 스 이 고 F 는 Object 에서 계승 합 니 다)
F ----> Function.prototype ----> Object.prototype ----> null

//  F.__proto__ === Function.prototype
// Function.prototype.__proto__ === Object.prototype
// Object.prototype.__proto__ === null

f 는 a, f 의 원형 체인 만 호출 할 수 있 습 니 다.(직관 적 해석: f 는 F 의 실례 로 모든 것 이 대상 이 고 f 는 Object 에서 계승 된다)
f ----> F.prototype ----> Object.prototype ----> null

//  f.__proto__ === F.prototype
// F.prototype.__proto__ === Object.prototype
// Object.prototype.__proto__ === null

f 의 프로 토 타 입 체인 에 Function. prototype 이 없어 서 b 에 접근 할 수 없습니다.
원형 대상 __proto__ 을 방문 하 는 것 은 비 표준 적 인 방법 이 며, ES5 표준 방법 은 Object. getPrototypeOf () 입 니 다.
여기까지 원형 체인 을 바탕 으로 하 는 계승 은 이미 뚜렷 하 다.
function Animal() {}

function Dog() {}

Dog.prototype.__proto__ = Animal.prototype;

var dog = new Dog();

// dog.__proto__ --> Dog.prototype;
// dog.__proto__.__proto__ --> Animal.prototype

ES5 표준 표기 법 은?
Dog.prototype = Object.create(Animal.prototype);

아 라 엘 의 포장 을 보 겠 습 니 다.
//      
function Ctor() {};

var createProto = Object.__proto__ ? function(proto) {
  return {
    __proto__: proto
  }
} : function(proto) {
  Ctor.prototype = proto;
  return new Ctor();
}

원형 체인 계승 을 실현 할 수 있 는 세 가지 방법 이 있 지만 저 는 new Ctor 가 가장 느 립 니 다. Object. create 가 그 다음 에 __proto__ 가 가장 빠 릅 니 다.
function Ctor() {}

function getProto1(proto, c) {
  Ctor.prototype = proto;
  var o = new Ctor();
  o.constructor = c;
  return o;
}

function getProto2(proto, c) {
  return Object.create(proto, {
    constructor: {
      value: c
    }
  })
}

function getProto3(proto, c) {
  return {
    __proto__: proto,
    constructor: c
  }
}

이어서 아래 를 보다.
function Class(o) {
  if (!(this instanceof Class) && isFunction(o)) {
    return classify(o);
  }
}

function classify(cls) {
  cls.extend = Class.extend;
  cls.implement = implement;
  return cls;
}

이러한 표기 법 은 new 키 워드 를 사용 하지 않 을 때 인자 를 호출 하 는 것 입 니 다. 예 를 들 어:
수정: 지원 되 지 않 는 방식 으로 호출 합 니 다.
function Animal() {}
Animal.prototype.talk = function() {}

//Class(Animal); Animal     extend   implement   
var Dog = Class(Animal).extend({
  swim: function() {}
})

Class 의 세 가지 변종 속성 new Extends Implements이 세 가지 속성 은 특수 처 리 를 할 것 이다.
Class.Mutators = {
  //      ,      
  Extends: function(parent) {
    var existed = this.prototype;
    //           
    var proto = createProto(parent.prototype);
    mix(proto, existed);
    //         
    proto.constructor = this;
    this.prototype = proto;
    //    superclass    ,       
    this.superclass = parent.prototype;
  },
  //     ,          
  Implements: function(items) {
    //        
    isArray(items) || (items = [ items ]);
    var proto = this.prototype, item;
    while (item = items.shift()) {
      //        (Function),     (Object),   。
      mix(proto, item.prototype || item);
    }
  },
  Statics: function(staticProperties) {
    //         。
    mix(this, staticProperties);
  }
}

다시 한 번 Statics 방법 을 보 자. 그것 은 속성 을 섞 는 데 쓰 인 다.
세 개의 변종 속성 이 실 행 됩 니 다.
function implement(properties) {
  var key, value;
  for (key in properties) {
    value = properties[key];
    if (Class.Mutators.hasOwnProperty(key)) {
      Class.Mutators[key].call(this, value);
    } else {
      this.prototype[key] = value;
    }
  }
}

자, 가장 중요 한 방법 implement 이 왔 습 니 다. 클래스 를 만 드 는 데 사 용 됩 니 다. 부모 클래스 를 지정 할 수 있 습 니 다.
Class.create = function(parent, properties) {
  //         ,     Class
  if (!isFunction(parent)) {
    properties = parent;
    parent = null;
  }
  properties || (properties = {});
  //       Extends   ,       
  parent || (parent = properties.Extends || Class);
  properties.Extends = parent;
  //          
  function SubClass() {
    //          
    parent.apply(this, arguments);
    //            ,initialize
    if (this.constructor === SubClass && this.initialize) {
      this.initialize.apply(this, arguments);
    }
  }
  //         ,       
  if (parent !== Class) {
    Mix(SubClass, parent, parent.StaticsWhiteList);
  }
  //          ,      ,      
  implement.call(SubClass, properties);
  //             
  return classify(SubClass);
}

마지막 으로 계승 방법 Class.create 을 살 펴 보 자. classify 의 클래스 는 하위 클래스 를 계속 만 들 수 있다.
Class.extend = function(properties) {
  properties || (properties = {});
  //         
  properties.Extends = this;
  return Class.create(properties);
}

마지막 으로 도구 류, Helpers 를 간단하게 소개 합 니 다.
//     ,       
function mix(r, s, wl) {
  for (var p in s) {
    //     :   for in        hasOwnProperty。        
    if (s.hasOwnProperty(p)) {
      if (wl && indexOf(wl, p) === -1) continue;
      if (p !== "prototype") {
        r[p] = s[p];
      }
    }
  }
}

// [].indexOf   ES5    ,          。
//            polyfill    。
var indexOf = Array.prototype.indexOf ? function(arr, item) {
  return arr.indexOf(item);
} : function(arr, item) {
  for (var i = 0, len = arr.length; i < len; i++) {
    if (arr[i] === item) {
      return i;
    }
  }
  return -1;
}

//      ,   Object.prototype.toString        [[class]]
var toString = Object.prototype.toString;
var isArray = Array.isArray || function(val) {
  return toString.call(val) === "[object Array]";
}
var isFunction = function(val) {
  return toString.call(val) === "[object Function]";
}

좋은 웹페이지 즐겨찾기