`

jQuery中深浅拷贝原理分析及实现(较为复杂的,做了详细的判断)

阅读更多
//测试Chrome版本  40.0.2214.115 m

//如有错误欢迎指出

//在此做一些相关方法的测试
//第一个each
//将来改成jq的时候为了方便,速度更快,防止覆盖,直接这样定义
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){
	//第一判断,如果不是object类型直接返回false
	//第二判断是否是节点类型
	//第三window
	if(type(obj)!=="object" ||obj.nodeType||isWindow(obj)){
		return false;
	}
	//当是{}或者是new Object() 时为真,这两种是符合的  只有object对象的原型中有这个方法
	if(hasOwn.call(obj.constructor.prototype,"isPrototypeOf")){
		return true;
	}
	
};

//第五个方法extend拷贝
var extend=function(){
	//第一方面分深浅拷贝   deep
	//第二方面   在jquery中分为向jquery对象添加对象或方法,在此是向window下添加对象或方法,
	//另一个就是一对象或方法向其它的对象上添加
	//
	var src,copy,copyIsArray,name,
		clone,//递归时要传的参数
		options,//要拷贝的对象
		target=arguments[0]||{},
		length=arguments.length,
		i=1,
		deep=false;
		
		if(typeof(target)==="boolean"){
			target=arguments[1]||{};
			deep=true;
			i=i+1;
		}
		//实际上当参数为以下两种情况是  就是上面所说的第二方面
		//第一种是:直接就有一个参数  {}
		//第二个就是:两个参数  true,{}
		if(i===length){
			target=this;//this是window
			i=i-1;
		}
		//当target,不是对象,函数的这种情况也要排掉
		if(!typeof(target)==="object" && !typeof(target)==="function"){
			target={};
		}
		
		for(;i<length;i++){
			for(name in options=(arguments[i]!==null) && arguments[i]){
				src=target[name];
				copy=options[name];
				if(src===copy){
					continue;
				}
				copyIsArray=isArray(copy)
				//if(deep&&copy||(isPlainObject(copy))|| (copyIsArray=isArray(copy))){
				if(deep&&copy && (isPlainObject(copy))|| copyIsArray){
					if(copyIsArray){
						copyIsArray=false;
						clone=src && isArray(src) ? src :[];//若不是数组类型,改为数组类型
					}else{
						clone=src && isPlainObject(src) ? src :{};
					}
					
					target[name]=extend(deep,clone,copy);
				}else if(copy !==undefined){
					target[name]=copy;
				}
			}
		}
	return target;
};

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics