extend 方法在js框架中的設計


今天來分析下extend方法在各種js框架下的設計。這個函數的功能基本都是實現對象的拷貝功能,即將一個對象的所有屬屬性拷貝到另外一個對象上去,這個函數使用的頻率也很高,如果我們要將一個類的所有方法拷貝到另外方法上去,使用這個方法很方便的。

1)在百度tangram js 框架中的實現,

baidu.extend =
baidu.object.extend = function (target, source) {
    for (var p in source) {
        if (source.hasOwnProperty(p)) {
            target[p] = source[p];
        }
    }
    
    return target;
};
僅有2個參數,extend(target,source),第一個參數是目標對象,第二個參數是原對象 ,對原對象中的每個屬性進行判斷,如果是,那么將他拷貝到目標的對象上去。

 

2)在jquery 中的實現:

jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
//如果第一個值為bool值,那么就將第二個參數作為目標參數,同時目標參數從2開始計數
if ( typeof target === "boolean" ) {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
i = 2;
}
// 當目標參數不是object 或者不是函數的時候,設置成object類型的
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}
//如果extend只有一個函數的時候,那么將跳出后面的操作
if ( length === i ) {
target = this;
--i;
}
for ( ; i < length; i++ ) {
// 僅處理不是 null/undefined values
if ( (options = arguments[ i ]) != null ) {
// 擴展options對象
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
// 如果目標對象和要拷貝的對象是恆相等的話,那就執行下一個循環。
if ( target === copy ) {
continue;
}
// 如果我們拷貝的對象是一個對象或者數組的話
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
if ( copyIsArray ) {
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : [];
} else {
clone = src && jQuery.isPlainObject(src) ? src : {};
}
//不刪除目標對象,將目標對象和原對象重新拷貝一份出來。 
target[ name ] = jQuery.extend( deep, clone, copy );
// 如果options[name]的不為空,那么將拷貝到目標對象上去。
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}
// 返回修改的目標對象
return target;

}; 

jquery的實現原理和tangram差不多,也是講原對象的屬性分別拷貝到目標對象上去,不過jq可以接受的參數比tangram要多,他可以接受無限和參數,如果第一個參數為true的話,將執行深度拷貝,將原對象和目標對象中的某些屬性值合並起來。

 3)protype.js的實現方式

  function extend(destination, source) {
    for (var property in source)
      destination[property] = source[property];
    return destination;

  } 

也是遍歷原 對象的各種屬性,然后將他拷貝到目標對象上去。實現的方式和tangram類似。

 4)dojo的實現

dojo.extend = function(/*Object*/ constructor, /*Object...*/ props){
// summary:
// Adds all properties and methods of props to constructor's
// prototype, making them available to all instances created with
// constructor.
for(var i=1, l=arguments.length; i<l; i++){
d._mixin(constructor.prototype, arguments[i]);
}
return constructor; // Object

 

var extraNames, extraLen, empty = {};
for(var i in {toString: 1}){ extraNames = []; break; }
dojo._extraNames = extraNames = extraNames || ["hasOwnProperty", "valueOf", "isPrototypeOf",
"propertyIsEnumerable", "toLocaleString", "toString", "constructor"];
extraLen = extraNames.length;
dojo._mixin = function(/*Object*/ target, /*Object*/ source){
// summary:
// Adds all properties and methods of source to target. This addition
// is "prototype extension safe", so that instances of objects
// will not pass along prototype defaults.
var name, s, i;
for(name in source){
// the "tobj" condition avoid copying properties in "source"
// inherited from Object.prototype.  For example, if target has a custom
// toString() method, don't overwrite it with the toString() method
// that source inherited from Object.prototype
s = source[name];
//fixed by yupeng 判斷元素是否是對象的屬性
if(!(name in target) || (target[name] !== s && (!(name in empty) || empty[name] !== s))){
target[name] = s;
}
}
// IE doesn't recognize some custom functions in for..in
if(extraLen && source){
for(i = 0; i < extraLen; ++i){
name = extraNames[i];
s = source[name];
if(!(name in target) || (target[name] !== s && (!(name in empty) || empty[name] !== s))){
target[name] = s;
}
}
}
return target; // Object

dojo首先會封裝一個_mixin方法,該方法起到的作用其實就是extend該起到的作用,然后再背部調用_mixin()方法,封裝的extend方法可以接受多個參數,同時將原對象的每個屬性都拷貝到目標對象的原型方法上。 

技巧(extend方法的妙用):

1)實現組件參數的靈活配置,我們在寫組件的時候,可以使用一些默認的配置參數,但是如果用戶想定制一些特殊的樣式的話,可以使用extend方法

例如在寫jq插件的時候

(function($) { 

$.fn.xxxx= function(options) {

var defaults = {
a: false,
b: {},
c: false,
b: false
};

var params = $.extend({}, defaults, options || {}); 

//接下來對函數進行處理。 

})(jquery) 

2)實現類方法的拷貝。 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM