JavaScript脚本

对Object的extend是一个常用的功能。举一个例子,由于javascript 没有重载(overload),而且函数的参数类型是没有定义的,所以很多时候我们都传入一个对象来作为参数已方便控制。通常在函数里面给了参数对象的默认值,这个时候就需要通过extend来把传入的参数覆盖进默认参数,如:

代码:

   1.  giant.ui.imageshow = function(options) {
   2.         this.opts = $.extend({}, giant.ui.imageshow.defaults, options);
   3. }
   4. giant.ui.imageshow.defaults = {
   5.       id:"imageshow",
   6.       isAuto:true,
   7.       speed:3000
   8. };

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
参数
target (Object) : 待修改对象。
object1 (Object) : 待合并到第一个对象的对象。
objectN (Object) : (可选) 待合并到第一个对象的对象。

但框架中内置的这个extend有明显的缺陷,那就是不能继承对象中的对象。还是举一个例子来说明:

代码:

   1.  var obj1 = {},
   2. var obj2={name:"karry",email:"karry@a.com",tel:{homeTel:"158255",officeTel:"02112585"}}
   3. obj1 = $.extend({},obj1 ,obj2 );

结果obj1 只有name 和email属性,而有与tel本身就是一个对象,tel里面的homeTel和officeTel没有继承过去。

我的目标就是实现这种对子对象的子属性也一起复制(继承)的功能,不管他嵌套有多深。

首先我们看看这个方法的参数,有三个参数,target 目标对象,source 源对象,deep 是否复制(继承)对象中的对象,如果deep为true则继承所有,为false则和jquery的实现方式一样,不会继承子对象。

复制内容到剪贴板
代码:
Object.extend = function(target, /*optional*/source, /*optional*/deep) {}

我只把第一个参数target设为必选参数,而source 和deep都设为可选参数。这样就会遇到一个问题,如果使用的时候只传如两个参数,怎么确认第二个参数是 对应的source还是deep?所以我需要判断传入的第二个参数的类型。

复制内容到剪贴板
代码:
   1.  target = target || {};   //target默认为空
   2. var sType = typeof source;
   3. //如果第二个参数的类型为未定义或者为布尔值
   4. if( sType === 'undefined' || sType === 'boolean' ) {
   5.     deep = sType === 'boolean' ? source : false;
   6.     source = target;    //把target赋值给source,
   7.     target = this;      //这里的this指的是Object
   8.  }

有人可能对最后面的两行代码有疑问,我的处理方式是这样的。如果target和source两个参数都存在,且source不是布尔值,那么,就把source对象的内容复制给target.否则,把target对象复制给Object对象。deep默认为false.

为了安全起见,我们还需要判断一下,如果souce满足了上面的条件,但它不是Object对象,或者它是一个Function对象(这涉及到一些其他的问题),我们也没办法对其进行复制的。这个时候我们把souce设为空的Object,也就是并不进行复制操作。

复制内容到剪贴板
代码:
   1.  if( typeof source !== 'object' && Object.prototype.toString.call(source) !== '[object Function]' )
   2.         source = {};

注:Function对象在执行typeof 操作时 也会返回“object”,但我们没办法对其进行正确的复制(至少在我这个方法里面不行),所以我必须剔除出来。

下面就是循环进行复制了。这里利用了递归

代码:

   1.  var i=1,option;
   2. // 外层循环就是为了把依次修改options,先设为target,后设为source
   3. while(i <= 2) {               
   4.         options = i === 1 ? target : source;
   5.         if( options != null ) {
   6.             //内层循环复制对应的属性
   7.             for( var name in options ) {                                      
   8.                 var src = target[name], copy = options[name];
   9.                 if(target === copy)
  10.                     continue;
  11.                 //如果deep设为true,且该属性是一个对象
  12.                 if(deep && copy && typeof copy === 'object' && !copy.nodeType)
  13.                     //递归
  14.                     target[name] = this.extend(src ||(copy.length != null ? [] : {}), copy, deep);
  15.                 else if(copy !== undefined)
  16.                     target[name] = copy;
  17.             }
  18.         }
  19.         i++;
  20.     }

这里利用了递归的方式,依次复制对象里面的对象。这个功能就做完了。全部代码如下:

 

代码:

   1.  /*
   2. * @param {Object} target 目标对象。
   3. * @param {Object} source 源对象。
   4. * @param {boolean} deep 是否复制(继承)对象中的对象。
   5. * @returns {Object} 返回继承了source对象属性的新对象。
   6. */
   7. Object.extend = function(target, /*optional*/source, /*optional*/deep) {
   8.     target = target || {};
   9.     var sType = typeof source, i = 1, options;
  10.     if( sType === 'undefined' || sType === 'boolean' ) {
  11.         deep = sType === 'boolean' ? source : false;
  12.         source = target;
  13.         target = this;
  14.     }
  15.     if( typeof source !== 'object' && Object.prototype.toString.call(source) !== '[object Function]' )
  16.         source = {};
  17.   
  18.     while(i <= 2) {
  19.         options = i === 1 ? target : source;
  20.         if( options != null ) {
  21.             for( var name in options ) {
  22.                 var src = target[name], copy = options[name];
  23.                 if(target === copy)
  24.                     continue;
  25.                 if(deep && copy && typeof copy === 'object' && !copy.nodeType)
  26.                     target[name] = this.extend(src ||
  27.                             (copy.length != null ? [] : {}), copy, deep);
  28.                 else if(copy !== undefined)
  29.                     target[name] = copy;
  30.             }
  31.         }
  32.         i++;
  33.     }
  34.     return target;
  35. };

使用示例:

 

代码:
   1.  var source = {id:1, name:'Jack Source'}, target = {name:'Jack Target', gender:1,tel:{homeTel:"158255",officeTel:"02112585"}};
   2. var newObj1 = Object.extend(target, source);
                                                                                             引用自他人文章
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值