自己动手实现 jQuery Callbacks 完整功能
上次利用中午的时间实现了部分功能的jQuery Callbacks类 , 具体可以参考上一篇 自己动手实现 jQuery Callbacks ,现在利用快下班的时间实现了其余的全部功能 :callbacks.disable , callbacks.disabled, callbacks.fired,callbacks.fireWith, callbacks.lock, callbacks.locked ,然后重构了下代码结构, 将实现放入了匿名函数内, 然后通过工厂方法 window.callbacks 返回实例,以免每次使用必须 new .
具体代码如下, 有兴趣和时间的可以对照jQuery版本的Callbacks对比下 :
( function ( window, undefined ) { // Simulate jQuery.Callbacks object function Callbacks( options ) { var ops = { once: false, memory: false, unique: false, stopOnFalse: false }, ar = [], lastArgs = null, firedTimes = 0, _disabled = false, _locked = false; if ( typeof options === 'string' && options.trim() !== '' ) { var opsArray = options.split( /\s+/ ); for ( var i = 0; i < options.length; i++ ) { if ( opsArray[i] === 'once' ) ops.once = true; else if ( opsArray[i] === 'memory' ) ops.memory = true; else if ( opsArray[i] === 'unique' ) ops.unique = true; else if ( opsArray[i] === 'stopOnFalse' ) ops.stopOnFalse = true; } } function hasName( name ) { var h = false; if ( typeof name === 'string' && name !== null && name.trim() !== '' && ar.length > 0 ) { for ( var i = 0; i < ar.length; i++ ) { if ( ar[i].name === name ) { h = true; break; } } } return h; } // add a function this.add = function ( fn ) { if ( typeof fn === 'function' ) { if ( ops.unique ) { // check whether it had been added before if ( fn.name !== '' && hasName( fn.name ) ) { return this; } } ar.push( fn ); if ( ops.memory ) { // after added , call it immediately fn.call( this, lastArgs ); } } return this; }; // remove a function this.remove = function ( fn ) { if ( typeof ( fn ) === 'function' && fn.name !== '' && ar.length > 0 ) { for ( var i = 0; i < ar.length; i++ ) { if ( ar[i].name === fn.name ) { ar.splice( i, 1 ); } } } return this; }; // remove all functions this.empty = function () { ar.length = 0; return this; }; // check whether it includes a specific function this.has = function ( fn ) { var f = false; if ( typeof ( fn ) === 'function' && fn.name !== '' && ar.length > 0 ) { for ( var i = 0; i < ar.length; i++ ) { if ( ar[i].name === fn.name ) { f = true; break; } } } return f; }; this.disable = function () { _disabled = true; return this; }; this.disabled = function () { return _disabled; }; this.fired = function () { return firedTimes > 0; }; function _fire( context, args ) { if ( _disabled || ops.once && firedTimes > 0 || _locked ) { return; } if ( ar.length > 0 ) { var r; for ( var i = 0; i < ar.length; i++ ) { r = ar[i].call( context, args ); if ( ops.stopOnFalse && r === false ) { break; } } } firedTimes++; if ( ops.memory ) { lastArgs = args; } }; this.fireWith = function ( context, args ) { context = context || this; _fire( context, args ); return this; }; this.fire = function ( args ) { _fire( this, args ); return this; }; this.lock = function () { _locked = true; return this; }; this.locked = function () { return _locked; }; }; // exposed to global as a factory method window.callbacks = function ( options ) { return new Callbacks( options ); }; } )( window );
为了测试fireWith ,增加了一个新的测试函数fn4
var fn1 = function ( v ) { console.log( 'fn1 ' + ( v || '' ) ); }; var fn2 = function ( v ) { console.log( 'fn2 ' + ( v || '' ) ); return false; }; function fn3( v ) { console.log( 'fn3 ' + ( v || '' ) ); }; function fn4( args ) { console.log( 'context is ' + this.toString() + ' argument is ' + args ); };
1.测试fireWith
var cb=callbacks() ;
cb.add(fn4)
cb.fireWith() // context is [object Object] argument is undefined
cb.fireWith(1) // context is 1 argument is undefined
cb.fireWith(window,1) // context is [object Window] argument is 1
2. 测试 lock
var cb=callbacks('memory');
cb.add(fn1) ; // fn1
cb.fire(1) // fn1 1
cb.add(fn2) // fn2 1
cb.lock() // 没有输出
cb.locked() // true
cb.fire(2) // 没有输出
3. 测试disable
var cb=callbacks();
cb.add(fn1) ;
cb.fire(1) // fn1 1
cb.disable() ;
cb.disabled() // true
cb.fire(1) // 没有输出
通过以上重复造轮子, 对jQuery.Callbacks了解了也更多了一些 。接下来再造造jQuery其他方面的轮子,以学习和强化js 吧。。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述