jQuery中回调函数的原理及实现下

//测试Chrome版本  40.0.2214.115 m

//如有错误欢迎指出

//回调函数分析上 http://ezizoo.iteye.com/blog/2204399  
//下面所讲是回调函数下

//重点
//此次添加 回调函数的三种状态
//所写的js可直接放入html中运行


//首先三种状态都在什么时候做判断
//onece 也就是执行回调的时候 fire()的时候判断是否已经fired==true
//unique 在添加函数的判断数组中是否有这个函数
//memory 在添加函数加上一句判断,当memory为真时,那么在cb.fire()执行后添加的方法也会被再次fire()
//需要有一个记录回调到哪一个函数的下标

//思路已经说了,看代码可直接到Callbacks方法这


//下面的一些方法前面都做了分析
//如有不懂可以看下我以前对这些方法的说明

var toString={}.toString;
var class2type={};
var hasOwn={}.hasOwnProperty;
var isArray=Array.isArray;
var indexOf=[].indexOf;

var each=function(obj,callback){
	var 
		value,
		length=obj.length,
		i=0,
		isArray=isArrayLike(obj);
		//两种情况
		//类数组
		if(isArray){
			for(;i<length;i++){
				//若是返回false,则直接跳出
				value=callback.call(obj,i,obj[i]);
				if(value===false){
					break;
				}
			}
		}else{
			for(i in obj){
				value=callback.call(obj,i,obj[i]);
				if(value===false){
					break;
				}
			}
		}
		return obj;
};

//第二个判断是否像数组一样的对象

var isArrayLike=function(obj){
	var 
		length=obj.length;
		
	//判断为空
	if(obj==null){
		return false;
	}
	
	if(type(obj)==="object" ||typeof(obj)==="function"){
		return false;
	}
	
	return type(obj)==="array" ||length===0 || (length>0 &&(length-1) in obj);
};

//第三个判断类型
var type=function(obj){
	//排除为空的
	if(obj==null){
		return obj+"";
	}
	//做判断,如果是object或者function类型的时候
	//不是执行后面
	return  typeof obj==="object" ||typeof obj==="function"  ? class2type[toString.call(obj)] : typeof obj;
};

each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(_,name){
	class2type["[object "+name+"]"]=name.toLowerCase();  
});

var isFunction=function(obj){
	return type(obj);
};
var isWindow=function(obj){
	return obj!==null && obj.window===window;
};

var isPlainObject=function(obj){

	if(type(obj)!=="object" ||obj.nodeType||isWindow(obj)){
		return false;
	}
	if(hasOwn.call(obj.constructor.prototype,"isPrototypeOf")){
		return true;
	}
	
};

//一个确定数组中是否存在这个值的函数
var inArray=function(arr,elem,i){
	return arr===null ? -1 :indexOf.call(arr,elem,i);
};

//第一个添加onece
//第二个添加memory  //只要在添加函数的时候过滤掉就行
var Callbacks=function(options){
	options=type(options)==="string" ? createOptions(options) :{};
	var 
		i,
		fired,
		firing,
		list=[],
		fireIndex=list.length,
		stack=!options.onece && [];
		//定义一个函数,将数组全部执行一次
		fire=function(){
			for(;list && fireIndex<list.length;i++,fireIndex++){
				//list[i]();
				//alert(this);
				list[fireIndex].call(arguments[0]);
			}
			fired=true;
		},
		self={
			add:function(){
				(function add(args){
					//对传进来的参数进行解析
					//以后可使用each遍历
					for(i=0;i<args.length;i++){
						if(!options.unique && typeof(args[i])==="function"||(options.unique && inArray(list,args[i])<0)){
							//list[i]=arguments[i]; 
							list.push(args[i]);
						}
					}
				})(arguments);
				
				if(options.memory){
					fire(this);
				}
				return this;
			},
			fire:function(){
				//if(options.onece && fired){
				//	fire(this);
				//}else{	
				//}
				//若是写成上述,当onece为false时,第一次就过不去
				//再写个fireWith()方法
				self.fireWith(this);
				return this;
			},
			fireWith:function(){
				if(list && (!fired || stack)){
					fire(this);
				}
				return this;
			}
		};
	return self;
};

//写个函数将几种状态解析出来
//参数形式如下'onece','memory'
var createOptions1=function(){
	var object={};
	each(arguments,function(_,flag){
		object[flag]=true;
	});
	return object;
};

//换一种写法
//参数形式如下'onece memory'
var reg=/\S+/g;
var createOptions=function(){
	var object={};
	each(arguments[0].match(reg),function(_,flag){
		object[flag]=true;
	});
	return object;
};

console.info(createOptions('onece unique'));

//附件中有html测试

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值