araleのソースコードのclass編を読みます.


更新:araleソースのatribute編を読みます.
アールはアリ、オープンソースのコミュニティのスターである玉伯です.開発されたセットはとても優美で、玉伯のオープンソース精神を絶賛しています.私はあなたのファンです.
ここで私はこのソースコードの悟りを共有します.間違ったところがあれば、ご指摘をお願いします.~ω ̄=
まず原型に基づく継承について話します.
まず、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のプロトタイプチェーンにFuntion.prototypeはありませんので、bにはアクセスできません.
なお、プロトタイプ__proto__非標準的な方法であり、ES 5標準的な方法はObject.get ProttypeOf()である.
ここでは、プロトタイプチェーンの継承が明らかになりました.
function Animal() {}

function Dog() {}

Dog.prototype.__proto__ = Animal.prototype;

var dog = new Dog();

// dog.__proto__ --> Dog.prototype;
// dog.__proto__.__proto__ --> Animal.prototype
ES 5に基づく表記は
Dog.prototype = Object.create(Animal.prototype);
araleのパッケージを見に来ました.
//      
function Ctor() {};

var createProto = Object.__proto__ ? function(proto) {
  return {
    __proto__: proto
  }
} : function(proto) {
  Ctor.prototype = proto;
  return new Ctor();
}
プロトタイプのチェーン継承が可能な3つの書き方がありますが、new Ctorをテストするのは一番遅いです.Object.creaeteの次は、__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キーワードを呼び出した場合、パラメータ 修正:サポートされていないnewの呼び出しです.
function Animal() {}
Animal.prototype.talk = function() {}

//Class(Animal); Animal     extend   implement   
var Dog = Class(Animal).extend({
  swim: function() {}
})
Classの三つのバリエーションExtendsImplementsStaticsimplementこの3つの属性は特殊処理されます.
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);
  }
}
また、Class.create方法を見てください.属性を混ぜるためのものです.
3つの変数の属性が実行されます.
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;
    }
  }
}
はい、一番重要な方法Class.extend来ました.これはクラスを作るためのもので、親の種類を指定できます.
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.extend = function(properties) {
  properties || (properties = {});
  //         
  properties.Extends = this;
  return Class.create(properties);
}
最後の最後に、簡単にその工具類を紹介します.
//     ,       
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]";
}