JQ的继承方法
使用方法:
// jQuery.extend 将一个方法扩展到函数下面,叫扩展静态方法
// jQuery.fn.extend 将一个方法扩展到原型对象下面,扩展实例方法
jQuery.extend = jQuery.fn.extend
// 当只写一个对象自变量的时候,JQ中扩展插件的形式
$.extend({
aaa: function(){
alert(1);
},
bbb: function(){
alert(2);
}
});
$.aaa();
$.bbb();
// 扩展JQ实例方法
$.fn.extend({
aaa: function(){
alert(3);
},
bbb: function(){
alert(4);
}
});
$().aaa();
$().bbb();
// 这里的this相当于$
$.extend(); -> this -> $ -> this.aaa -> $.aaa()
// 这里的this相当于$.fn
$.fn.extend(); -> this -> $.fn -> this.aaa -> $().aaa()
// 当写多个对象自变量的时候,后面的对象都是扩展到第一个对象身上
var a = {};
$.extend(a, { name: 'hello'}, {age: 30});
console.log(a);
{
age: 30,
name: 'hello'
}
// 还可以做 深拷贝 和 浅拷贝
// 浅拷贝,两个指针指向同一个对象
var a = {};
var b = { name: 'hello' };
$.extend(a, b);
a.name = 'hi';
alert(b.name); // 可以正常修改
var a = {};
var b = { name: { age: 30 } };
$.extend(a, b);
a.name.age = 20;
alert(b.name.age); // 可以正常修改 20
// 如何让里面的age不受影响呢
var a = {};
var b = { name: { age: 30 } };
// 添加true为深拷贝,就是两个不同的对象
$.extend(true, a, b);
a.name.age = 20;
console.log(a); // { name: { age: 20 } }
console.log(b); // { name: { age: 30 } }
jQuery源码解析
// 只有一个对象自变量
// JQ扩展插件
$.extend({
aaa: function(){
alert(1);
}
});
// 扩展JQ实例方法
$.fn.extend({
aaa: function(){
alert(3);
}
});
// 多个对象自变量,后面的对象都是扩展到第一个对象身上
var a = {};
$.extend(a, { name: 'hello'}, {age: 30}, {sex: 'man'});
// 浅拷贝和深拷贝都是两个对象
// 浅拷贝:拷贝第一层
var a = {};
var b = { name: 'hello', age: 30 };
var a = {};
var b = { name: { age: 30 } };
$.extend(a, b);
// 深拷贝:两个是不同的对象
var a = {};
var b = { name: { age: 30 } };
$.extend(true, a, b);
/**
* 首先要分清楚要扩展到谁身上,如果没有扩展对象,就创建一个 {}
* 在确定好扩展对象之后
* 再确定是深拷贝还是浅拷贝(或是只有一个对象)
* 浅拷贝:
* 横向遍历{{}, {}, {}} 深度遍历只需遍历一层{{name:{age:{oo: 'rr'}}, kk: 'll'}, {sex: 'hh'}}, name = 原来的对象{age:{oo: 'rr'}}, 不需要再往下递归遍历
* 深拷贝:
* {{}, {}, {}} 横向遍历每一个对象和属性,{{name:{age:30}}, {sex: 'hh'}}, 递归遍历属性是对象的情况,每次都创建新的对象
*
*/
// jQuery.extend 将一个方法扩展到函数下面,叫扩展静态方法
// jQuery.fn.extend 将一个方法扩展到原型对象下面,扩展实例方法
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
// 目标元素(扩展到谁身上)
// 多个对象自变量:扩展到 arguments[0] 身上
target = arguments[0] || {},
i = 1, // 开始遍历的下标
length = arguments.length,
// 默认不是深拷贝
deep = false;
// $.extend(true, a, b); 深拷贝的情况
if ( typeof target === "boolean" ) {
deep = target;
// arguments[1]是否为 null undefined "" " 0
target = arguments[1] || {};
i = 2;
}
// 因为要扩展到target身上,所以必须是对象或函数
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}
// 看是不是插件的情况
// $.extend({
// aaa: function(){
// alert(1);
// },
// bbb: function(){
// alert(2);
// }
// });
// $.aaa();
// $.bbb();
if ( length === i ) {
// this 是 $ 或者 jQuery.fn = jQuery.prototype
target = this;
--i;
}
for ( ; i < length; i++ ) {
// $.extend(a, { name: 'hello'}, {age: 30});
// 从第二个参数开始,可以写n多个对象
// 看一下argument后面的那些对象是否为空,并将arguments[i]赋值给options
if ( (options = arguments[ i ]) != null ) {
// name 是 键
for ( name in options ) {
// src是存在目标中的值
src = target[ name ];
// copy是options中所对应的值
copy = options[ name ];
// 防止循环引用
// $.extend( a, { name: a });
if ( target === copy ) {
continue;
}
// 深拷贝
// 如果是深拷贝
// var a = {};
// var b = { name: { age: 30 } };
// $.extend(true, a, b);
// 比如说b就是一个对象
// 也可以写成数组的形式 var c = [];
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
/*
var a = { name : {job: 'it' }};
var b = { name: { age: 30 }}
$.extend(true, a, b);
console.log(a);
{
name: {
job: 'it',
age: 30
}
}
*/
// 如果它是数组的情况
if ( copyIsArray ) {
copyIsArray = false;
// clone是要扩展到的对象,对应这种情况{{name:{age:{oo: 'rr'}, kk: 'll'}}, {sex: 'hh'}}
// 中的name,包含两个属性,所以得扩展到name身上,不能扩展到别地儿
clone = src && jQuery.isArray(src) ? src : [];
} else {
clone = src && jQuery.isPlainObject(src) ? src : {};
}
// Never move original objects, clone them
target[ name ] = jQuery.extend( deep, clone, copy );
// 浅拷贝
} else if ( copy !== undefined ) {
// 扩展到target身上
target[ name ] = copy;
}
}
}
}
// Return the modified object
return target;
};