jQuery中的扩展方法extend是一个很重要的方法,我们可以利用这个方法编写我们自己的插件。
可以先看看这个方法的定义,源码摘自jquery-1.9.1.js:
jQuery.extend = jQuery.fn.extend = function() {
var src, copyIsArray, copy, name, options, clone,
//target:初始为第一个参数
target = arguments[0] || {},
i = 1,
length = arguments.length,
//deep:表示是否执行深拷贝
deep = false;
// 如果第一个参数是boolean类型,如果为true.则进行深拷贝,false浅拷贝
if ( typeof target === "boolean" ) {
deep = target;
//这时候target取第二个参数
target = arguments[1] || {};
//
i = 2;
}
// 如果target初始值不对,如:字符串...
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}
// 如果仅仅只有一个参数被传入,那么target就为当前对象jQuery || jQuery.fn.
if ( length === i ) {
target = this;
--i;
}
for ( ; i < length; i++ ) {
// 如果参数不为空
if ( (options = arguments[ i ]) != null ) {
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
// 避免options中如果出现格式错误或者冲突引起死循环
if ( target === copy ) {
continue;
}
// 递归处理,如果deep为true且copy是一个数组或者是一个对象,则进行深拷贝
// jQuery.isPlainObject(cbject):是否是一个通过{}或者new Object()创建的一个纯粹对象
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
//如果copy是一个数组
if ( copyIsArray ) {
//重置为false
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : [];
// 如果是一个对象
} else {
clone = src && jQuery.isPlainObject(src) ? src : {};
}
//递归,将options[name]的值进行深拷贝到src对象中
target[ name ] = jQuery.extend( deep, clone, copy );
//如果copy已经定义,则扩展基本对象
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}
// 返回目标对象
return target;
};
看懂了源码之后,我们就可以对该方法进行运用了。
1、如果要对jQuery本身进行方法扩展,那么可以利用jQuery.extend(args1);
jQuery(document).ready(function(){
jQuery.extend({
add:function(){
var result = 0,
len = arguments.length;
for(var i=0;i<len;i++) {
if(jQuery.isNumeric(arguments[i])) {
result += arguments[i];
}
}
return result;
},
subtract:function(){
}
});
alert(jQuery.add(1,2,3,4.2,5));
});
2、如果是要对自己定义的对象进行方法或者参数的扩展:jQuery.extend({},args1,args2....);
var settings = jQuery.extend({},{
height:"100px",
width :"200px"
});
alert(settings.width);
例2:
var person = jQuery.extend({},{name:"xuzengqiang",age:"22"},{"height":"181cm","weight":"70kg"});
alert(person.name);
3、如果要对jQuery对象进行方法扩展:jQuery.fn.extend(arg1,arg2.....);
;(function($){
jQuery.fn.ensure = function(){
$(this).click(function(){
alert("ok!");
});
};
})(jQuery);
$(".test").ensure();
这个时候我们这样写的话就不能够类似jQuery链式结构一样,**()继续调用jQuery的方法了。因为它没有返回对象。
我们可以这样改写一下:
;(function($){
jQuery.fn.ensure = function(){
return this.each(function(){
$(this).click(function(){
alert("ok!");
});
});
};
})(jQuery);
$(".test").ensure().css({"width":"100px","height":"30px"});
深拷贝与浅拷贝:
我们看了源码后知道,要执行深拷贝,那么第一个参数需设置成true. jQuery.extend(deep,arg1,arg2.....),
什么是深拷贝,看下面这个例子:
var person = jQuery.extend({},
{username:"xuzengqiang", info:{age:22,country:"China"}},
{username:"smith", info:{country:"America"}}
);
alert(person.info.age); //undefined
如果是浅拷贝,那么打印的undefined,因为此时的person对象为:
var person = {
username : "smith",
info : {
country : "America"
}
};
那如果是深拷贝:
var person = jQuery.extend(true, {},
{username:"xuzengqiang", info:{age:22,country:"China"}},
{username:"smith", info:{country:"America"}}
);
alert(person.info.age);
打印22。此时person对象为:
var person = {
username : "smith",
info : {
age : 22,
country : "America"
}
};
jQuery插件写法可以参考上面的对jQuery对象方法的扩展。