?
思考是从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]