JavaScript Object的extend是一個常用的功能
更新時間:2009年12月02日 00:42:08 作者:
對Object的extend是一個常用的功能。舉一個例子,由于javascript 沒有重載(overload),而且函數(shù)的參數(shù)類型是沒有定義的,所以很多時候我們都傳入一個對象來作為參數(shù)已方便控制。
通常在函數(shù)里面給了參數(shù)對象的默認值,這個時候就需要通過extend來把傳入的參數(shù)覆蓋進默認參數(shù),如:
代碼:
giant.ui.imageshow = function(options) {
this.opts = $.extend({}, giant.ui.imageshow.defaults, options);
}
giant.ui.imageshow.defaults = {
id:"imageshow",
isAuto:true,
speed:3000
};
Jquery 的框架中給了一個extend工具:
jQuery.extend(target,obj1,[objN])
用一個或多個其他對象來擴展一個對象,返回被擴展的對象。
用于簡化繼承。
Extend one object with one or more others, returning the original, modified, object.
This is a great utility for simple inheritance.
返回值--Object
參數(shù)
target (Object) : 待修改對象。
object1 (Object) : 待合并到第一個對象的對象。
objectN (Object) : (可選) 待合并到第一個對象的對象。
但框架中內(nèi)置的這個extend有明顯的缺陷,那就是不能繼承對象中的對象。還是舉一個例子來說明:
代碼:
var obj1 = {},
var obj2={name:"karry",email:"karry@a.com",tel:{homeTel:"158255",officeTel:"02112585"}}
obj1 = $.extend({},obj1 ,obj2 );
結(jié)果obj1 只有name 和email屬性,而有與tel本身就是一個對象,tel里面的homeTel和officeTel沒有繼承過去。
我的目標就是實現(xiàn)這種對子對象的子屬性也一起復(fù)制(繼承)的功能,不管他嵌套有多深。
首先我們看看這個方法的參數(shù),有三個參數(shù),target 目標對象,source 源對象,deep 是否復(fù)制(繼承)對象中的對象,如果deep為true則繼承所有,為false則和jquery的實現(xiàn)方式一樣,不會繼承子對象。
代碼:
Object.extend = function(target, /*optional*/source, /*optional*/deep) {}
我只把第一個參數(shù)target設(shè)為必選參數(shù),而source 和deep都設(shè)為可選參數(shù)。這樣就會遇到一個問題,如果使用的時候只傳如兩個參數(shù),怎么確認第二個參數(shù)是 對應(yīng)的source還是deep?所以我需要判斷傳入的第二個參數(shù)的類型。
代碼:
target = target || {}; //target默認為空
var sType = typeof source;
//如果第二個參數(shù)的類型為未定義或者為布爾值
if( sType === 'undefined' || sType === 'boolean' ) {
deep = sType === 'boolean' ? source : false;
source = target; //把target賦值給source,
target = this; //這里的this指的是Object
}
有人可能對最后面的兩行代碼有疑問,我的處理方式是這樣的。如果target和source兩個參數(shù)都存在,且source不是布爾值,那么,就把source對象的內(nèi)容復(fù)制給target.否則,把target對象復(fù)制給Object對象。deep默認為false.
為了安全起見,我們還需要判斷一下,如果souce滿足了上面的條件,但它不是Object對象,或者它是一個Function對象(這涉及到一些其他的問題),我們也沒辦法對其進行復(fù)制的。這個時候我們把souce設(shè)為空的Object,也就是并不進行復(fù)制操作。
代碼:
if( typeof source !== 'object' && Object.prototype.toString.call(source) !== '[object Function]' )
source = {};
注:Function對象在執(zhí)行typeof 操作時 也會返回“object”,但我們沒辦法對其進行正確的復(fù)制(至少在我這個方法里面不行),所以我必須剔除出來。
下面就是循環(huán)進行復(fù)制了。這里利用了遞歸。
代碼:
var i=1,option;
// 外層循環(huán)就是為了把依次修改options,先設(shè)為target,后設(shè)為source
while(i <= 2) {
options = i === 1 ? target : source;
if( options != null ) {
//內(nèi)層循環(huán)復(fù)制對應(yīng)的屬性
for( var name in options ) {
var src = target[name], copy = options[name];
if(target === copy)
continue;
//如果deep設(shè)為true,且該屬性是一個對象
if(deep && copy && typeof copy === 'object' && !copy.nodeType)
//遞歸
target[name] = this.extend(src ||(copy.length != null ? [] : {}), copy, deep);
else if(copy !== undefined)
target[name] = copy;
}
}
i++;
}
這里利用了遞歸的方式,依次復(fù)制對象里面的對象。這個功能就做完了。全部代碼如下:
代碼:
/*
* @param {Object} target 目標對象。
* @param {Object} source 源對象。
* @param {boolean} deep 是否復(fù)制(繼承)對象中的對象。
* @returns {Object} 返回繼承了source對象屬性的新對象。
*/
Object.extend = function(target, /*optional*/source, /*optional*/deep) {
target = target || {};
var sType = typeof source, i = 1, options;
if( sType === 'undefined' || sType === 'boolean' ) {
deep = sType === 'boolean' ? source : false;
source = target;
target = this;
}
if( typeof source !== 'object' && Object.prototype.toString.call(source) !== '[object Function]' )
source = {};
while(i <= 2) {
options = i === 1 ? target : source;
if( options != null ) {
for( var name in options ) {
var src = target[name], copy = options[name];
if(target === copy)
continue;
if(deep && copy && typeof copy === 'object' && !copy.nodeType)
target[name] = this.extend(src ||
(copy.length != null ? [] : {}), copy, deep);
else if(copy !== undefined)
target[name] = copy;
}
}
i++;
}
return target;
};
使用示例:
代碼:
var source = {id:1, name:'Jack Source'}, target = {name:'Jack Target', gender:1,tel:{homeTel:"158255",officeTel:"02112585"}};
var newObj1 = Object.extend(target, source);
代碼:
復(fù)制代碼 代碼如下:
giant.ui.imageshow = function(options) {
this.opts = $.extend({}, giant.ui.imageshow.defaults, options);
}
giant.ui.imageshow.defaults = {
id:"imageshow",
isAuto:true,
speed:3000
};
Jquery 的框架中給了一個extend工具:
jQuery.extend(target,obj1,[objN])
用一個或多個其他對象來擴展一個對象,返回被擴展的對象。
用于簡化繼承。
Extend one object with one or more others, returning the original, modified, object.
This is a great utility for simple inheritance.
返回值--Object
參數(shù)
target (Object) : 待修改對象。
object1 (Object) : 待合并到第一個對象的對象。
objectN (Object) : (可選) 待合并到第一個對象的對象。
但框架中內(nèi)置的這個extend有明顯的缺陷,那就是不能繼承對象中的對象。還是舉一個例子來說明:
代碼:
復(fù)制代碼 代碼如下:
var obj1 = {},
var obj2={name:"karry",email:"karry@a.com",tel:{homeTel:"158255",officeTel:"02112585"}}
obj1 = $.extend({},obj1 ,obj2 );
結(jié)果obj1 只有name 和email屬性,而有與tel本身就是一個對象,tel里面的homeTel和officeTel沒有繼承過去。
我的目標就是實現(xiàn)這種對子對象的子屬性也一起復(fù)制(繼承)的功能,不管他嵌套有多深。
首先我們看看這個方法的參數(shù),有三個參數(shù),target 目標對象,source 源對象,deep 是否復(fù)制(繼承)對象中的對象,如果deep為true則繼承所有,為false則和jquery的實現(xiàn)方式一樣,不會繼承子對象。
代碼:
復(fù)制代碼 代碼如下:
Object.extend = function(target, /*optional*/source, /*optional*/deep) {}
我只把第一個參數(shù)target設(shè)為必選參數(shù),而source 和deep都設(shè)為可選參數(shù)。這樣就會遇到一個問題,如果使用的時候只傳如兩個參數(shù),怎么確認第二個參數(shù)是 對應(yīng)的source還是deep?所以我需要判斷傳入的第二個參數(shù)的類型。
代碼:
復(fù)制代碼 代碼如下:
target = target || {}; //target默認為空
var sType = typeof source;
//如果第二個參數(shù)的類型為未定義或者為布爾值
if( sType === 'undefined' || sType === 'boolean' ) {
deep = sType === 'boolean' ? source : false;
source = target; //把target賦值給source,
target = this; //這里的this指的是Object
}
有人可能對最后面的兩行代碼有疑問,我的處理方式是這樣的。如果target和source兩個參數(shù)都存在,且source不是布爾值,那么,就把source對象的內(nèi)容復(fù)制給target.否則,把target對象復(fù)制給Object對象。deep默認為false.
為了安全起見,我們還需要判斷一下,如果souce滿足了上面的條件,但它不是Object對象,或者它是一個Function對象(這涉及到一些其他的問題),我們也沒辦法對其進行復(fù)制的。這個時候我們把souce設(shè)為空的Object,也就是并不進行復(fù)制操作。
代碼:
復(fù)制代碼 代碼如下:
if( typeof source !== 'object' && Object.prototype.toString.call(source) !== '[object Function]' )
source = {};
注:Function對象在執(zhí)行typeof 操作時 也會返回“object”,但我們沒辦法對其進行正確的復(fù)制(至少在我這個方法里面不行),所以我必須剔除出來。
下面就是循環(huán)進行復(fù)制了。這里利用了遞歸。
代碼:
復(fù)制代碼 代碼如下:
var i=1,option;
// 外層循環(huán)就是為了把依次修改options,先設(shè)為target,后設(shè)為source
while(i <= 2) {
options = i === 1 ? target : source;
if( options != null ) {
//內(nèi)層循環(huán)復(fù)制對應(yīng)的屬性
for( var name in options ) {
var src = target[name], copy = options[name];
if(target === copy)
continue;
//如果deep設(shè)為true,且該屬性是一個對象
if(deep && copy && typeof copy === 'object' && !copy.nodeType)
//遞歸
target[name] = this.extend(src ||(copy.length != null ? [] : {}), copy, deep);
else if(copy !== undefined)
target[name] = copy;
}
}
i++;
}
這里利用了遞歸的方式,依次復(fù)制對象里面的對象。這個功能就做完了。全部代碼如下:
代碼:
復(fù)制代碼 代碼如下:
/*
* @param {Object} target 目標對象。
* @param {Object} source 源對象。
* @param {boolean} deep 是否復(fù)制(繼承)對象中的對象。
* @returns {Object} 返回繼承了source對象屬性的新對象。
*/
Object.extend = function(target, /*optional*/source, /*optional*/deep) {
target = target || {};
var sType = typeof source, i = 1, options;
if( sType === 'undefined' || sType === 'boolean' ) {
deep = sType === 'boolean' ? source : false;
source = target;
target = this;
}
if( typeof source !== 'object' && Object.prototype.toString.call(source) !== '[object Function]' )
source = {};
while(i <= 2) {
options = i === 1 ? target : source;
if( options != null ) {
for( var name in options ) {
var src = target[name], copy = options[name];
if(target === copy)
continue;
if(deep && copy && typeof copy === 'object' && !copy.nodeType)
target[name] = this.extend(src ||
(copy.length != null ? [] : {}), copy, deep);
else if(copy !== undefined)
target[name] = copy;
}
}
i++;
}
return target;
};
使用示例:
代碼:
復(fù)制代碼 代碼如下:
var source = {id:1, name:'Jack Source'}, target = {name:'Jack Target', gender:1,tel:{homeTel:"158255",officeTel:"02112585"}};
var newObj1 = Object.extend(target, source);
您可能感興趣的文章:
- js如何獲取object類型里的鍵值
- JS 對象(Object)和字符串(String)互轉(zhuǎn)方法
- js如何打印object對象
- JavaScript 判斷判斷某個對象是Object還是一個Array
- 刪除Javascript Object中間的key
- 詳解Javascript中的Object對象
- Javascript中判斷變量是數(shù)組還是對象(array還是object)
- Javascript Object.extend
- 深入理解JavaScript中的對象復(fù)制(Object Clone)
- JS Object.preventExtensions(),Object.seal()與Object.freeze()用法實例分析
相關(guān)文章
JS調(diào)用頁面表格導(dǎo)出excel示例代碼
這篇文章主要介紹了JS調(diào)用頁面表格導(dǎo)出excel的具體實現(xiàn),需要的朋友可以參考下2014-03-03javascript閉包傳參和事件的循環(huán)綁定示例探討
按常理循環(huán)綁定事件,但是得到的結(jié)果卻不是想要的,下面有個不錯的示例,可以為大家詳細分解下2014-04-04一文詳解preact的高性能狀態(tài)管理Signals
這篇文章主要介紹了一文詳解preact的高性能狀態(tài)管理Signals,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,感興趣的朋友可以參考一下2022-09-09javascript 支持鏈式調(diào)用的異步調(diào)用框架Async.Operation
javascript 支持鏈式調(diào)用的異步調(diào)用框架Async.Operation2009-08-08