jQuery设计模式(二)

Iterator(迭代器)

模式
Iterator是一种设计模式,其中,迭代器顺序访问聚合对象的元素,无需公开其基本形式。
迭代器封装特定迭代如何发生的内部结构。对于jQuery的jQuery.fn.each()迭代器,我们实际上能够使用jQuery.each()后面的底层代码来遍历一个集合,而不需要阅读或者理解提供这种功能的后台工作代码。
这种模式可以被视为一种特殊的facade,我们显式地处理与迭代相关的问题。

    $.each(["a","b","c","d"],function(index , value){
        console.log(index + ":" + value )
    });
    $("li").each(function (index) {
        console.log(index  + ":" + $(this).text());
    })
这里我们看到jQuery.fn.each()的源码:
each: function( callback, args ) {
        return jQuery.each( this, callback, args );
    }
随后是jQuery.each()后面的代码,它处理了两种遍历对象:
    each: function( obj, callback, args ) {
        var value,
            i = 0,
            length = obj.length,
            isArray = isArraylike( obj );

        if ( args ) {
            if ( isArray ) {
                for ( ; i < length; i++ ) {
                    value = callback.apply( obj[ i ], args );

                    if ( value === false ) {
                        break;
                    }
                }
            } else {
                for ( i in obj ) {
                    value = callback.apply( obj[ i ], args );

                    if ( value === false ) {
                        break;
                    }
                }
            }

        // A special, fast, case for the most common use of each
        } else {
            if ( isArray ) {
                for ( ; i < length; i++ ) {
                    value = callback.call( obj[ i ], i, obj[ i ] );

                    if ( value === false ) {
                        break;
                    }
                }
            } else {
                for ( i in obj ) {
                    value = callback.call( obj[ i ], i, obj[ i ] );

                    if ( value === false ) {
                        break;
                    }
                }
            }
        }

        return obj;
    }

延迟初始化

延迟初始化是一种设计模式,它能延迟昂贵的过程,直到第一个实例需要时。其中一个示例就是jQuery中的ready()函数,当DOM准备就绪时,它仅执行一次回调。

实例ready方法

jQuery.fn.ready = function( fn ) {
    // Add the callback
    jQuery.ready.promise().done( fn );

    return this;
};

实际实现

ready: function( wait ) {

 // Abort if there are pending holds or we're already ready if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { return; } // Remember that the DOM is ready jQuery.isReady = true; // If a normal DOM Ready event fired, decrement, and wait if need be if ( wait !== true && --jQuery.readyWait > 0 ) { return; } // If there are functions bound, to execute readyList.resolveWith( document, [ jQuery ] ); // Trigger any bound ready events if ( jQuery.fn.triggerHandler ) { jQuery( document ).triggerHandler( "ready" ); jQuery( document ).off( "ready" ); } }

Proxy(代理)模式

我们有时候需要控制对象的访问权限和上下文,这就是Proxy模式有用的地方。
当一个昂贵的对象应被实例化的时,Proxy模式可以帮助我们对其进行控制,提供高级的方法来引用对象,或修改对象,让它在特定的上下文中以一种特殊方式发挥作用。
在jQuery核心中,存在jQuery.proxy()方法,它接受函数作为参数,并返回一个始终具有特定上下文的新对象。这确保函数中的this值是我们所需要的值。
在下面的示例中它就很有用,在click事件处理程序内使用计时器时延迟执行。

  $("button").on("click", function () {
      setTimeout(function () {
          $(this).addClass("active"); //this指向window
      },100)
  })

为了解决这个问题,我们可以使用jQuery.proxy()来实现代理模式类型。通过使用我们希望赋给this的函数和值来调用它,它实际上会返回一个函数,它会在正确的上下文保留该值。

   $("button").on("click", function () {
        setTimeout($.proxy(function(){
            console.log(this.value);
        },this),100);
    })

jQuery源码中的实现:

    proxy: function( fn, context ) {
        var tmp, args, proxy;

        if ( typeof context === "string" ) {
            tmp = fn[ context ];
            context = fn;
            fn = tmp;
        }

        // Quick check to determine if target is callable, in the spec
        // this throws a TypeError, but we will just return undefined.
        if ( !jQuery.isFunction( fn ) ) {
            return undefined;
        }

        // Simulated bind
        args = slice.call( arguments, 2 );
        proxy = function() {
            return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
        };

        // Set the guid of unique handler to the same of original handler, so it can be removed
        proxy.guid = fn.guid = fn.guid || jQuery.guid++;

        return proxy;
    }

你可能感兴趣的:(设计模式,jquery,jquery设计模式)