1. 程式人生 > >jQuery.Callbacks 原始碼解讀二

jQuery.Callbacks 原始碼解讀二

var optionsCache = {},
    // Used for splitting on whitespace
    core_rnotwhite = /\S+/g;

// Convert String-formatted options into Object-formatted ones and store in cache
function createOptions( options ) {
    // 多個變數指向同一物件(或陣列)引用時,其中一個變數修改了被引用物件的內部結構,其他引用變數也會表現出來
    var object = optionsCache[ options ] = {};
    jQuery.each( options.match( core_rnotwhite ) 
|| [], function( _, flag ) { object[ flag ] = true; // optionsCache[ options ][ flag ] = true; }); return object; } jQuery.Callbacks = function( options ) { // Convert options from String-formatted to Object-formatted if needed // (we check in cache first) options = typeof
options === "string" ? // 快取所有的引數標誌,當再次傳遞已傳遞過的引數標誌,則使用快取值optionsCache[ options ] ( optionsCache[ options ] || createOptions( options ) ) : // 說明也可以這樣$.Callbacks({once:true, memory:true})使用 jQuery.extend( {}, options ); var // Flag to know if list is currently firing
firing, // Last fire value (for non-forgettable lists) memory, // Flag to know if list was already fired fired, // End of the loop when firing firingLength, // Index of currently firing callback (modified by remove if needed) firingIndex, // First callback to fire (used internally by add and fireWith) firingStart, // Actual callback list list = [], // Stack of fire calls for repeatable lists stack = !options.once && [], // Fire callbacks // data為fireWith內部整理的args陣列 fire = function( data ) { memory = options.memory && data; fired = true; // 處理在add中,options.memory = true;的情況 firingIndex = firingStart || 0; firingStart = 0; firingLength = list.length; firing = true; for ( ; list && firingIndex < firingLength; firingIndex++ ) { // 正在執行的回撥返回值為false 且 options.stopOnFalse為true,則終止回撥佇列的執行 if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { memory = false; // To prevent further calls using add break; } } firing = false; if ( list ) { // 處理正在執行的回撥中執行fireWith的操作; if ( stack ) { if ( stack.length ) { fire( stack.shift() ); } } // 上一分支狀態為回撥執行過,且可以執行多次 // 此時 options.once = true; 這裡將list設定為[],只是確保下次執行fire時,無回撥執行 // 但是如果 options.memory = true; 仍然會執行add中的fire操作,因為此時回撥列表中已有回撥 else if ( memory ) { list = []; } else { self.disable(); } } }, // Actual Callbacks object self = { // Add a callback or a collection of callbacks to the list add: function() { if ( list ) { // First, we save the current length var start = list.length; (function add( args ) { jQuery.each( args, function( _, arg ) { var type = jQuery.type( arg ); if ( type === "function" ) { // 回撥不唯一 或 唯一且不存在,則push if ( !options.unique || !self.has( arg ) ) { list.push( arg ); } } // 遞迴檢查 else if ( arg && arg.length && type !== "string" ) { // Inspect recursively add( arg ); } }); })( arguments ); // Do we need to add the callbacks to the // current firing batch? // 正在執行的回撥執行了add操作,則更新firingLength if ( firing ) { firingLength = list.length; // With memory, if we're not firing then // we should call right away // 如果options.memory為true,則再次執行fire,且引數相同,fire中的firingIndex為此時的firingStart } else if ( memory ) { firingStart = start; fire( memory ); } } return this; }, // Remove a callback from the list remove: function() { if ( list ) { jQuery.each( arguments, function( _, arg ) { var index; while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { // 查詢到所對應的索引,則移除索引項 list.splice( index, 1 ); // Handle firing indexes // 正在執行的回撥執行了remvoe操作,則更新firingLength和firingIndex的值 if ( firing ) { if ( index <= firingLength ) { firingLength--; } if ( index <= firingIndex ) { firingIndex--; } } } }); } return this; }, // Check if a given callback is in the list. // If no argument is given, return whether or not list has callbacks attached. has: function( fn ) { return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); }, // Remove all callbacks from the list empty: function() { list = []; return this; }, // Have the list do nothing anymore // 禁用add,remove,fire主要方法的工作 disable: function() { list = stack = memory = undefined; return this; }, // Is it disabled? disabled: function() { return !list; }, // Lock the list in its current state lock: function() { // 如果回撥執行過,則將阻止self.fire操作 // 但如果 options.memory = true,則仍然會執行fire操作 stack = undefined; // 回撥未執行,則禁用 if ( !memory ) { self.disable(); } return this; }, // Is it locked? locked: function() { return !stack; }, // Call all callbacks with the given context and arguments fireWith: function( context, args ) { args = args || []; args = [ context, args.slice ? args.slice() : args ]; // 回撥未執行 或 已執行且可以執行多次 if ( list && ( !fired || stack ) ) { // 正在執行的回撥函式執行了fireWith操作( 暗指回撥列表已執行過,且可以執行多次,stack = []; ) // 該函式需要條件執行,或有移除該函式的操作,否則陷入死迴圈,詳見例2 if ( firing ) { stack.push( args ); } // 正在執行的回撥函式沒有執行fireWith操作 else { fire( args ); } } return this; }, // Call all the callbacks with the given arguments fire: function() { self.fireWith( this, arguments ); return this; }, // To know if the callbacks have already been called at least once fired: function() { return !!fired; } }; return self; };

相關推薦

jQuery.Callbacks 原始碼解讀

var optionsCache = {}, // Used for splitting on whitespace core_rnotwhite = /\S+/g; // Convert String-formatted options into Object-formatte

JDK之ArrayDeque原始碼解讀()

目錄   copyElements(T[] a) ArrayDeque() ArrayDeque(int numElements) addFirst(E e) addLast(E e) offerFirst(E e) offerLast(E e) p

JDK之ArrayList原始碼解讀()

目錄   remove(int index) remove(Object o) clear() addAll(Collection c) addAll(int index, Collection c) removeRange(int fromIndex, i

jieba分詞原始碼解讀

上一篇文章說到結巴分詞用了包裝器實現了在 get_DAG 函式執行器生成了 trie 樹。在這篇文章中我們要研究一下jieba分詞中的 DAG(有向無環圖,全稱:directed acyclic g

Python Web Flask原始碼解讀()——路由原理

關於我 一個有思想的程式猿,終身學習實踐者,目前在一個創業團隊任team lead,技術棧涉及Android、Python、Java和Go,這個也是我們團隊的主要技術棧。 Github:https://github.com/hylinux1024 微信公眾號:終身開發者(angrycode) 接上一篇的話

swoft| 原始碼解讀系列: 啟動階段, swoft 都幹了些啥?

date: 2018-8-01 14:22:17title: swoft| 原始碼解讀系列二: 啟動階段, swoft 都幹了些啥?description: 閱讀 sowft 框架原始碼, 瞭解 sowft 啟動階段的那些事兒 小夥伴剛接觸 swoft 的時候會感覺 壓力有點大, 更直觀的說法是 難. 開發

jQuery原始碼解讀之init函式

jQuery的構造方法: // 直接new了一個物件。同時根據jQuery.fn = jQuery.prototype,jQuery.fn相當於jQuery.prototype。 jQuery = function( selector, context ) { return

Spring原始碼解讀之Spring MVC HandlerMapping元件(

一、HandlerMapping HandlerMapping作用是根據request找到相應的處理器Handler和Interceptors,並將Handler和Interceptors封裝成HandlerExecutionChain 物件返回。Handler

Netty原始碼解讀)Netty中的buffer

感謝網友【黃億華】投遞本稿。 上一篇文章我們概要介紹了Netty的原理及結構,下面幾篇文章我們開始對Netty的各個模組進行比較詳細的分析。Netty的結構最底層是buffer模組,這部分也相對獨立,我們就先從buffer講起。 What: buffer二三事 buffer中文名又叫緩衝區,按

jQuery原始碼解讀

           在使用jQuery的過程中,深深體會著jQuery的宗旨:write less, do more. 在解讀jQuery書上有句話我特別的喜歡,送給大家:"jQuery說,給你一個方法,你能讓網際網路炫目富有!",看到這裡,我們不禁會想起阿基米德的那句精

jquery原始碼解讀1

(function( global, factory ) {if ( typeof module === "object" && typeof module.exports === "object" ) {// For CommonJS and CommonJ

jquery 原始碼解讀

jquery 原始碼大概10000多行,每行都會解析可能不是很現實,可能也只會更新一版,這都看心情。 (function(global,factory){...})() 在這部分主要就是匿名函式 註釋:匿名函式的好處:自執行裡面所有東西都是區域性的,防

jQuery原始碼學習()

回撥物件Callbacks 回撥物件Callbacks就是用來管理回撥函式佇列的。 引數說明 它提供幾個便捷的處理引數 once: 確保這個回撥列表只執行一次 memory: 保持以前的值,將新增到這個列表的後面的最新的值立即執行呼叫任何回撥 u

Electrum 錢包原始碼解讀

前言 程式碼地址如下: 下面開始程式碼的執行。 在路徑electrum-master下找到 run_electrum 檔案,將檔案中的所有方法逐一打上斷點之後,使用Run->Toggle Line Breakpoint 後 debug 來逐行執行,可以

apache ftpServer原始碼解讀與收穫(

二.相關配置 1.伺服器配置 server元素 <serverxmlns="http://mina.apache.org/ftpserver/spring/v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLo

安卓andbase框架原始碼解讀

上一次分析了andbase框架的AbActivity 安卓andbase框架原始碼解讀(一),不知道有沒有讓大家對這個框架產生點興趣,這次我要分析的是一個平常比較常用也比較簡單但是還挺煩人的知識點:下載圖片,當然現在有很多框架比如ImageLoader,Volley裡的專門

Netty原始碼解讀------------客戶端接入繫結()

下面接著看下面這段程式碼 //Binder裡面的程式碼 public void channelOpen( ChannelHandlerContext ctx, ChannelStateEv

Redux原始碼解讀

上篇文章我們分析了createStore和combineReducers檔案,這一篇我們分析剩下的檔案。 首先是bindActionCreators檔案,這個檔案十分簡單 function bindActionCreator(actionCreator, dispa

jQuery-過濾選擇器

字符 sel gre bsp orm span tex jquer code 1、屬性過濾選擇器 $(function(){ $(‘div[title]‘).css(‘background‘,‘red‘); //有title屬性的所有div元素

jquery中的$.ajax次封裝 從而多次調用 今天一整天都在想這個事情

send attribute 面試官 clas display str kit || enc 當然了 我封裝的是$.ajax 可以傳參數 多次調用請求接口 為啥我們這地方不註重前端呢 我都不知道為啥去堅持 不說了 上代碼 js文件 $ajax.js $(fun