当前位置: 代码迷 >> Web前端 >> 关于each的一些思忖
  详细解决方案

关于each的一些思忖

热度:208   发布时间:2012-09-29 10:30:01.0
关于each的一些思考

?

思考是从jQuery的一段代码开始的。

?

?

jQuery.each({
	slideDown: genFx("show", 1),
	slideUp: genFx("hide", 1),
	slideToggle: genFx("toggle", 1),
	fadeIn: { opacity: "show" },
	fadeOut: { opacity: "hide" }
}, function( name, props ) {
	jQuery.fn[ name ] = function( speed, callback ) {
		return this.animate( props, speed, callback );
	};
});

?

ps:以前明哥问我想要研究js的那些部分,我当时很自然地说了fx.................

?

回到正题,我选的代码是1.4.1,其实在JQuery的源码中你会发现很多这样的模式

?

?

//1.4.1的版本里面大概是23处地方这样的模式
//当然里面的第一个参数可以是[],{}
//下面我就简单地以["bind","one"]举例
jQuery.each(["bind","one"],function(i,name){
         //我这就简单地以jQuery.fn举例  
           jQuery.fn[name] = function(){
               .....................
           }
})

?

好吧 为了让大家明白,我们先来思考一下这种each的实现。

?

第一看看jQuery的each实现。

----ps : 这个each不是$().each

?

?

/*
一些chm或者在线的手册上会告诉你$.each有两个参数
@param {Object}  object ----需要遍历的对象或者数组
@param {Function}  callback(可选)  ---每一个成员执行的回调
但是你看源码的时候你会发现原来有3个参数
*/
each: function( object, callback, args ) {
		var name, i = 0,
                 //object的length       
                 length = object.length,
	//jQuery.isFunction(object) 判断是否是function		
       isObj = length === undefined || jQuery.isFunction(object);

		if ( args ) {
			if ( isObj ) {
				for ( name in object ) {
					if ( callback.apply( object[ name ], args ) === false ) {
						break;
					}
				}
			} else {
				for ( ; i < length; ) {
					if ( callback.apply( object[ i++ ], args ) === false ) {
						break;
					}
				}
			}

		// A special, fast, case for the most common use of each
		} else {
                       //一般我们多走这个,因为没有定义args--undefined
			if ( isObj ) {
                             //for object
				for ( name in object ) {
					if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
						break;
					}
				}
			} else {
                             //for array
				for ( var value = object[0];
					i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
			}
		}
                //返回object
		return object;
	},

?

下面先举一个简单的object参数为array的例子

?

?

/*
我这边定义的object为array 
@i是index
@n是对应objetc[i]
*/
$.each( ["a","b","c"], function(i, n){
		 ?( "Item #" + i + ": " + n );
		});

//这个jQuery的$.each在处理object为array的时候的源码
//其实就是开始的时候value是object[0]  //this的指向!!
//如果回调函数返回的不是false的话 value每一次变成 object[++i]
//call的时候参数第一个是object[i]对象;第二个是index--i ;第三个是object[i]
for ( var value = object[0];
					i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}	

?

?

再看看处理object为{}的例子

?

?

 /*
我这边定义的是object为真正的object {}
回调的参数@param i 是key
               @param n是value
*/

$.each( { name: "zhangyaochun", age: "24" }, function(i, n){
  alert( "Pro: " + i + ", Value: " + n );
});


//我们来看一下jQuery的$.each处理object为{}的时候

for ( name in object ) {
//进行for in的循环
//call的第一个参数是object[name]  //这个this指向!!
//call的第二个参数是name     //属性
//call的第三个参数是object[name] //值
//同样如果回调返回的是false就Break				
if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
						break;
					}
				}

?

?

其实这个问题在我研究tangram和自己编写自己的凤凰lib的时候就开始think....

?

?

/*
*each-traverse a object and follow the iterator to return a obj*
*@function*
*@param {Object} source*
*@param {Function} iterator ---function(item,key)*
*@return {Object}*
*/
ZYC.object.each = function(source,iterator){
    var returnValue,key,item;
	if(typeof iterator == 'function'){
	    for(key in source){
                        //加了一层hasOwnProperty
			if(source.hasOwnProperty(key)){
			   item = source[key];
                          //call的时候this指向的是source
                          //然后后面的参数依次是value和key
			   returnValue = iterator.call(source,item,key);
			}
			//如果有返回值是false的话就break
			if(returnValue === false){
			   break;
			}
	   }
	}
	return  source;
};
?

?

?

最后还是讲一下自己的收获:思考的是一些api实现和动态扩展创建命名空间下的fn的方式,从而结合去编写改善自己的api实现方式

?

我在扩展我的fn的时候也参照了这样$.each的模式,动态的去扩展一下phoenix.fn[key]

  相关解决方案