首頁  >  文章  >  web前端  >  【Javascript】zepto源碼Callback分析

【Javascript】zepto源碼Callback分析

php是最好的语言
php是最好的语言原創
2018-08-06 15:21:181609瀏覽

Callback模組是用來管理回呼函數,也作為deferred延遲物件得基礎部分,現在一起來看看他的原始碼。
可選參數:

  Options:
    once: 是否最多执行一次,
    memory: 是否记住最近的上下文和参数
    stopOnFalse: 当某个回调函数返回false时中断执行
    unique: 相同得回调只被添加一次

這是可選參數,下面可以進行試驗:

var a = function (value) {
  console.log('a:' + value);
};
var b = function (value) {
  console.log('b:' + value);
};
var callbacks = $.Callbacks();
callbacks.add(a);
callbacks.fire(['hello']);
callbacks.add(b);
callbacks.fire('中');

下面是他的輸出結果:

a: hello,
a:中,
b:中

可以看到得是,當我們第二次fire得時候,a函數也會執行。
在加入參數進行實驗,首先加入memory

var callbacks = $.Callbacks({
  memory: true
});
callbacks.add(a);
callbacks.fire('hello');
callbacks.add(b);
输出:
a:hello,
b:hello

加入memory參數,memory記錄上一次觸發回呼函數,之後新增的函數都用這參數立即執行。在來看once的使用

var callbacks = $.Callbacks({
  once: true
});
callbacks.add(a);
callbacks.fire('hello');
callbacks.fire('中');
输出:
a:hello

可以看到的是,雖然執行了兩次fire方法,但只輸出了一次結果。其他兩個參數很好理解,細節的部分自己去嘗試。

$.Callbacks = function(options) {
  options = $.extend({}, options)
  var memory, 
    fired, 
    firing,
    firingStart,
    firingLength,
    firingIndex,
    list = [],
    stack = !options.once && []
}

再看看各個參數的意義,memory會在記憶模式下記住上一次觸發的上下文和參數,fired代表回調是否已經觸發過,firing表示回調正在觸發,firingStart回呼任務開始的位置,firingLength回呼任務的長度,firingIndex目前回呼的索引,list表示真實的回呼佇列,在不是觸發一次的情況下,用來快取觸發過程中沒有執行的任務參數。

fire = function(data) {
  memory = options.memory && data
  fired = true
  firingIndex = firingStart || 0
  firingStart = 0
  firingLength = list.length
  firing = true
  for ( ; list && firingIndex < firingLength ; ++firingIndex ) {
    if (list[firingIndex].apply(data[0], data[1]) === false && options.stopOnFalse) {
      memory = false
      break
    }
  }
  firing = false
  if (list) {
    if (stack) stack.length && fire(stack.shift())
    else if (memory) list.length = 0
    else Callbacks.disable()
  }
}

fire函數是唯一內建的函數,他的作用是用來觸發list的回呼執行,首先看看他傳入的參數,和咱們在外部呼叫$.Callbacks的fire還不太一樣,這裡的data是一個數組,data[0]表示上下文,data[1]是方法呼叫的參數。然後就是各個參數的初始化,memory表示如果options.memory為true,則保存data,fired為true,如果firingStart為0,那麼firingIndex 為0,firingStart置為0,正在觸發的回調標記firing為true。 
接著遍歷回呼列表,逐一執行回呼,這個裡邊的if判斷表示的是如果回呼函數回傳的是false並且options.stopOnFalse是false,則清空memory的快取。遍歷完成後,將執行的狀態改為false。如果list存在,stack也存在,把任務參數取出來,呼叫fire函數執行。如果memory存在,則清空列表,否則進行回調執行

最終這個檔案回傳的是Callbacks,我們來看看他的具體實作:

Callbacks = {
  add: function () {
    if (list) {
      var start = list.length,
        add = function (args) {
          $.each(args, funciton(_, arg) {
            if (typeof arg === &#39;function&#39;) {
              if (!options.unique || !Callbacks.has(arg)) list.push(arg);
            } else if (arg && arg.length && typeof arg !== &#39;string&#39;) add(arg);
          })
        }
      add(arguments)
      if (firing) firingLength = list.length;
      else if (memory) {
        firingStart = start;
        fire(memory)
      }
    }
    return this;
  }
}

這個函數主要的作用就是像list裡邊push回調。首先判斷list是否存在,如果存在,start賦值為list的長度,在內部加入一個add方法,內部add方法主要是在list中加入回調,如果我們傳入的參數是數組,就再次呼叫add方法。然後就是呼叫add方法,把arguments傳進去。如果回呼正在進行,則修正回呼任務的長度firingLength為目前任務清單的長度,以便後續新增的回呼函數可以執行。如果memory存在,則把開始設定為新新增清單的第一位,然後呼叫fire。 
我們再來看看fireWith的做法:

fireWith: function(context, args) {
  if (list && (!fired || stack)) {
    args = args || [];
    args = [context, args.slice ? args.slice() : args];
    if (firing) stack.push(args);
    else fire(args);
  }
  return this;
}

傳入的參數包含上下文,和參數清單。函數執行的條件是list存在且回呼沒有執行或stack存在,stack可以為空。首先對args進行重新賦值,args[0]是上下文,args[1]是複製過來的列表。如果回調正在進行,請向stack裡邊添加args,或者就執行args。

相關文章:

Zepto原始碼中Gesture模組介紹

Javascript中的Callback方法淺析

#

以上是【Javascript】zepto源碼Callback分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn