extend是jQuery中一個比較核心的代碼,如果有查看jQuery的源碼的話,就會發現jQuery在多處調用了extend方法。 作用 1. 對任意對象進行擴展 2. 擴展某個實例對象 3. 對jquery本身的實例方法進行擴展 實現 基礎版本, 對簡單對象進行擴展 jQuery.prototy ...
extend是jQuery中一個比較核心的代碼,如果有查看jQuery的源碼的話,就會發現jQuery在多處調用了extend方法。
作用
- 對任意對象進行擴展
- 擴展某個實例對象
- 對jquery本身的實例方法進行擴展
實現
基礎版本, 對簡單對象進行擴展
jQuery.prototype.extend = jQuery.extend = function(){
var target = arguments[0] || {}; //獲取第一個參數作為目標結果
var i = 1; //設置開始擴展的下標,擴展時第一個參數不會進行改變,不需要遍歷
var length = arguments.length;
var option;
if(typeof target !== 'object') {
target = {};
}
for(; i< length; i++){
option = arguments[i]
for(var name in option){
target[name] = option[name]
}
}
return target
}
//調用
var i = {a: 0};
var b = {c: 9};
console.log($().extend(i,b)) // {a:0, c:9}
升級版本1.0, 對複雜對象進行擴展。
在上面,我們已經寫出的extend的基礎版本,但是如果我們簡單測試一下,就會發現仍是有問題存在的。
我們可以使用上面的方法,對下麵的對象進行擴展
var n = {
al: 90,
m: {
d: 23,
}
}
var b = {m:{
c: 98
}};
console.log($().extend(n,b)) // {al: 90, m: { c: 98 }}
簡單的從結果來看,返回的結果並不符合我們的預期,基礎版本的方法似乎只是簡單的值替換而已。那麼來簡單升級一下代碼吧。
在升級代碼之前,需要瞭解一下關於淺拷貝和深拷貝的相關。
關於淺拷貝和深拷貝的那些事
- 淺拷貝,
對於淺拷貝,我的簡單理解就是: 淺拷貝就是對最錶面的層級進行拷貝,如果某一被拷貝對象的值發生了改變,最終的拷貝結果也會隨之發生改變。
var i = {a: 0};
var b = {c: 9};
console.log($().extend(i,b)) // {a: 90, c:9}
i.a = 90
- 深拷貝,深拷貝主要的是面對複雜對象,如果淺拷貝是對最錶面的一層進行拷貝,那麼深拷貝就是,對拷貝對象的每一個層級都進行拷貝,某種層面來說,勉強算得上是遞歸的淺拷貝吧,但是比較不同的是,深拷貝中,如果某一個被拷貝對象的值發生了改變,拷貝結果是不會隨之發生變化的,是一個獨立的存儲空間。
var n = {
al: 90,
m: {
d: 23,
}
}
var b = {m:{
c: 98
}};
console.log($().extend(true,{},n,b))
console.log(n)
n.al = "cs"
結果:
深拷貝extend代碼擴展
jQuery.extend是提供深拷貝的,需要將第一參數傳為true。
基本思路:
- 首先先對第一個傳入參數進行判斷,判斷是否是boolean類型,來決定是否需要進行深拷貝;
var deep = false;
if (typeof target === 'boolean') {
deep = target;
target = arguments[1];
i = 2; //因為第一參數為boolean,所以拷貝對象從argument[1]開始,但通常第一個拷貝對象是不需要比遍歷的,所以遍歷下標從2開始。
}
- 對需要遍歷的對象進行判斷,判斷是否是複雜類型。使用extend對jquery進行擴展。
if (length === i) { //此時extend參數只有一個,但是目標應該是this,所以獲取到this;
target = this; //但同時 i = 1;無法進行遍歷,所以將遍歷下標後退一位
i--;
}
jQuery.extend({
isArray: function(obj) {
return toString.call(obj) === '[object Array]';
},
isPainObj: function(obj) {
return toString.call(obj) === '[object Object]';
}
})
- extend方法改造。
jQuery.prototype.extend = jQuery.extend = function(){
var target = arguments[0] || {};
var i = 1;
var length = arguments.length;
var option, copy, src, copyisArray, clone;
for(; i< length; i++){
if((option = arguments[i]) != null ){
for(name in option) {
src = target[name];
copy = option[name];
if(jQuery.isPainObj(copy) || (copyisArray = jQuery.isArray(copy))) {
if(copyisArray) {
copyisArray = false;
clone = src && jQuery.isArray(src) ? src : [];
} else {
clone = src && jQuery.isPainObj(src) ? src : {};
}
target[name] = jQuery.extend(clone,copy)
} else if(copy !== undefined) {
target[name] = copy
}
}
}
}
return target
}
行了,到這裡為止,我們就已經完成了簡單的extend函數了,其實比較重要的是深拷貝和淺拷貝,關於這一點,下次再記錄吧。