jQuery插件扩展之$.extend初始【第一篇】

259 查看

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深拷贝与浅拷贝
jq文档中extend方法的使用格式
使用格式如上图,具有一个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^