国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

讀 arale 源碼之 class 篇

firim / 1130人閱讀

摘要:擁有了和方法的三個變種屬性這三個屬性會做特殊處理繼承的方法,只支持單繼承建立原型鏈來實現繼承強制改變構造函數提供語法糖,來調用父類屬性混入屬性,可以混入多個類的屬性將參數變成數組無論參數是類,還是對象,都混入。

更新:讀 arale 源碼之 attribute 篇

arale 是阿里、開源社區明星人物--玉伯,開發的一套組件,代碼相當優美,大贊玉伯的開源精神,我是您的粉絲。

這里分享下我對這段源代碼的感悟,若有錯誤的地方,煩請指正。= ̄ω ̄=

先談談基于原型的繼承。

先看看 segementfault 上討論的一道題。

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);
來看看 arale 的封裝
// 創建原型鏈
function Ctor() {};

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

有三種寫法可以實現原型鏈繼承,但是我測試 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 的三個變種屬性 Extends Implements Statics

這三個屬性會做特殊處理

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);
  }
}

再來看看 implement 方法, 它是用來混入屬性的。

三個變種屬性將被執行

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.create 來了,它是用來創建類的,可以指定父類。

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 ,被 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]";
}

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/85987.html

相關文章

  • arale 源碼 attribute

    摘要:系列文章讀源碼之篇提供基本的屬性添加獲取移除等功能。判斷是否為等對象特性檢查閉包實現塊作用域,不污染全局變量。找這個屬性,若沒有則返回空對象執行函數,返回被修改的值。 系列文章:讀 arale 源碼之 class 篇 attributes 提供基本的屬性添加、獲取、移除等功能。它是與實例相關的狀態信息,可讀可寫,發生變化時,會自動觸發相關事件 先來了解一下 Attribute 模塊要實...

    Magicer 評論0 收藏0
  • Arale源碼解析(3)——Base模塊和Aspect模塊

    摘要:本文同步自我的博客前言這個模塊實際上才是模塊系統中對外的模塊,它包含了之前介紹的類和類,以及自己內部的模塊和模塊,因此模塊是真正的基礎類。這兩個方法的作用就是針對類上的某個方法,給這個方法綁定先于其執行和后于其執行的回調函數。 本文同步自我的GitHub博客 前言 Base這個模塊實際上才是Arale模塊系統中對外的模塊,它包含了之前介紹的Class類和Events類,以及自己內部...

    stdying 評論0 收藏0
  • Arale源碼解析(1)——Class

    摘要:先來看源碼中,首先是做的是參數的處理工作,針對某些參數未傳的情況作了調整,最后達到的效果是的值為傳入的父類構造函數,如果沒有,設為。下一個語句其作用是處理父類構造函數沒有修改的屬性值并且有方法的時候,在上調用方法。 本文同步自我的GitHub 概述 Arale是支付寶開發的一套基礎類庫,提供了一整套前端模塊架構,基于CMD規范,所有模塊均是以sea.js的標準進行開發。其開發過程借...

    _ivan 評論0 收藏0
  • js 支持 Aspect 切面編程

    摘要:在方法執行后,再執行函數函數在執行時,接收的參數第一個是的返回值,之后的參數和傳給相同。的返回值源碼定義兩個出口定義一個可柯里化的函數,柯里化成函數指向基于生成的類的實例,如上例的如果該函數是第一次切面化綁定,則包裝該函數。 系列文章:讀 arale 源碼之 class 篇 使用 Aspect,可以允許你在指定方法執行的前后插入特定函數 before object.before(me...

    zhaot 評論0 收藏0
  • 2015 Hackathon 杭州站回顧BugLife

    摘要:今天我偷偷的去上喵了幾眼,發現我捉出來的,還沒被消滅掉,看來有必要發個郵件給高陽了。還得到了高陽的飯約,因為我們捉了好幾個的,高陽你別忘啊下面就上幾張我們的的靚照吧的獲獎自之后,我們還是很有自信能得個獎的。 BugLife的誕生記 先自我介紹下我們團隊,Wellming、Bell orchid、Retamia,三枚程序員,主要技能點PHP,目前在一家棒棒的做開源網校系統(EduSoho...

    SmallBoyO 評論0 收藏0

發表評論

0條評論

firim

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<