• 自己动手实现 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 吧。。 

  • 相关阅读:
    [数据结构与算法] 001—栈与队列(Python)
    [BLOG] Hexo之NexT配置过程中遇到的问题
    [Python] windows下beautifulsoup使用lxml解析使用报错
    [SQLTips] SQL优化技巧-批处理替代游标
    [SQLTips]NULLIF与ISNULL的交叉使用
    [SQLTips]查看锁和Kill 死锁进程
    Java基础学习——多线程之创建任务
    性能测试工具——Jmeter使用小结(一)
    Java基础学习——多线程之线程池
    初学Hadoop:利用VMWare+CentOS7搭建Hadoop集群
  • 原文地址:https://www.cnblogs.com/leonwang/p/jquerycallbacks.html
Copyright © 2020-2023  润新知