first ——>
$.extend作用不只是给jquery添加插件,它有三种基本的用法。
1.给jq的实例扩展多个方法:
var fun = {
toHide:function(){
$(this).hide();
},
toRed:function(){
$(this).css({color:'red'});
}
};
$.fn.extend(fun);
// $('div').toHide();
$('div').toRed();
2.给jq本身命名空间加方法:
var foo = {
toDou:function(num){
return num<10?'0'+num:''+num;
},
rnd:function(m,n){
return Math.floor(m+Math.random()*(n-m));
}
};
$.extend(foo);
console.log($.toDou($.rnd(0,33)));
3.扩展对象 (例: 用 b 扩展 a):
会在b对象上寻找a对象没有的属性复制到a上,而同名属性会被覆盖
var a = {
name:'dean',
age:18
};
var b = {
name:'leo',
job:'teacher'
};
var c = $.extend(a,b);
console.log(a);
console.log(b);
console.log(c);//Object {name: "leo", age: 18, job: "teacher"}
second ——>
$.entend深拷贝与浅拷贝
使用格式如上图,具有一个deep的布尔值可选属性,如果指定为true就会触发深拷贝,简单来讲深拷贝遇到属性为引用类型的时候,会复制一个副本而不是像浅拷贝一样去复制内存地址(指针)。
那么这里先用代码列出浅拷贝的特点:
var a = {
name:'Tom',
age:6,
skills:{
catch:'mouse',
eat:'pie',
call:'miao'
}
};
var b = {
name:'Jerry',
age:2,
skills:{
eat:'cheese',
work:'hole'
},
test:'copy'
};
var c = $.extend({},a,b);
//这个时候c是扩展了ab属性的对象,这里有一个特点:对于skills属性的复制,复制的是内存地址。也就是指针 这时通过 a或b改变skills, c中的skills同时会被改变。
//test change
a.name = 'dean';
b.name ='sam';
a.skills.eat = '1';
//这里会发现不变 因为b在a后面 扩展的时候重新把eat覆盖成cheese
//b.skills = {};//这个时候不变是因为 b的指向变了 而c从b那复制的指向仍然没变。
b.skills.eat = '2';//这个时候 b 和c 指向内存中同一个对象 ,所以 c的skills中eat被改为了2.
console.log('a: '+ JSON.stringify(a));
//{"name":"dean","age":6,"skills":{"catch":"mouse","eat":"1","call":"miao"}}
console.log('b: '+ JSON.stringify(b));
//{"name":"sam","age":2,"skills":{"eat":"2"},"test":"copy"}
console.log('c: '+ JSON.stringify(c));
//{"name":"Jerry","age":2,"skills":{"eat":"2","work":"hole"},"test":"copy"}
这就是当b.skills指向{}的时候的简易内存图。(虽然有点像鬼画的,O(∩_∩)O哈哈~)
那么到这里,聪明的同学们已经想到了,深拷贝是不是就会把引用类型的属性复制成一个副本,不会与之前的引用共用同一个对象。我们往下看:
var a = {
name:'Tom',
age:6,
skills:{
catch:'mouse',
eat:'pie',
call:'miao'
}
};
var b = {
name:'Jerry',
age:2,
skills:{
eat:'cheese',
work:'hole'
},
test:'copy'
};
var c = $.extend(true,{},a,b);
//这个时候c是扩展了ab属性的对象,添加了deep属性,这时通过 a或b改变skills c中的skills不会被改变。
//test change
a.name = 'dean';
b.name ='sam';
b.skills.eat = '2';
//这个时候由于是深复制,所以不会改动c中的skills
//而且它把 a 和 b skills对象属性内部的属性全部扩展到了 c 这也就是api文档所说的递归合并。
console.log('a: '+ JSON.stringify(a));
// {"name":"dean","age":6,"skills":{"catch":"mouse","eat":"pie","call":"miao"}}
console.log('b: '+ JSON.stringify(b));
// {"name":"sam","age":2,"skills":{"eat":"2","work":"hole"},"test":"copy"}
console.log('c: '+ JSON.stringify(c));
// {"name":"Jerry","age":2,"skills":{"catch":"mouse","eat":"cheese","call":"miao","work":"hole"},"test":"copy"}
到这里,同学们了解了$.extend深浅拷贝的区别了,细心的同学会发现一个细节,猜一猜在哪里? 不卖关子了 看截图:
这里无论是浅拷贝还是深拷贝,我都在前面加了一个{},这个是为了什么呢?
废话不多说,我们看代码:
var a = {name:1,job:'111'};
var b = {name:2,age:3};
var c = $.extend(a,b);
console.log(a); //{name: 2, job: "111", age: 3}
console.log(b); //{name: 2, age: 3}
console.log(c); //{name: 2, job: "111", age: 3}
//b 扩展 a 改变 a 返回扩展之后的对象 a ,这里用 c 接收。
var d = {name:4,job:'222'};
var e = {name:5,age:6};
var f = $.extend({},d,e);
console.log(d); //{name: 4, job: "222"}
console.log(e); //{name: 5, age: 6}
console.log(f); //{name: 5, job: "222", age: 6}
// d 和 e 扩展 {} 改变{} 返回扩展之后的对象 {} 这里用 f 接收。
//也就是说改变的对象永远是target对象,也就是deep属性后的参数(如果没指定deep属性则为第一个参数) ,所以这里如果想保留扩展之前的对象 可以采用将 target对象设置为{}的办法。
这就是$.extend的基本用法和深浅拷贝,下一节我们将对$.extend的jq源码进行分析,敬请期待,小伙伴们 拜拜喽! ^O^