JavaScript Object的extend是一个常用的功能

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

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
参数
target (Object) : 待修改对象。
object1 (Object) : 待合并到第一个对象的对象。
objectN (Object) : (可选) 待合并到第一个对象的对象。
但框架中内置的这个extend有明显的缺陷,那就是不能继承对象中的对象。还是举一个例子来说明:
代码:
复制代码 代码如下:

var obj1 = {},
var obj2={name:"karry",email:"karry@a.com",tel:{homeTel:"158255",officeTel:"02112585"}}
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?所以我需要判断传入的第二个参数的类型。
代码:
复制代码 代码如下:

target = target || {}; //target默认为空
var sType = typeof source;
//如果第二个参数的类型为未定义或者为布尔值
if( sType === 'undefined' || sType === 'boolean' ) {
deep = sType === 'boolean' ? source : false;
source = target; //把target赋值给source,
target = this; //这里的this指的是Object
}

有人可能对最后面的两行代码有疑问,我的处理方式是这样的。如果target和source两个参数都存在,且source不是布尔值,那么,就把source对象的内容复制给target.否则,把target对象复制给Object对象。deep默认为false.
为了安全起见,我们还需要判断一下,如果souce满足了上面的条件,但它不是Object对象,或者它是一个Function对象(这涉及到一些其他的问题),我们也没办法对其进行复制的。这个时候我们把souce设为空的Object,也就是并不进行复制操作。
代码:
复制代码 代码如下:

if( typeof source !== 'object' && Object.prototype.toString.call(source) !== '[object Function]' )
source = {};

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

var i=1,option;
// 外层循环就是为了把依次修改options,先设为target,后设为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;
//如果deep设为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++;
}

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

/*
* @param {Object} target 目标对象。
* @param {Object} source 源对象。
* @param {boolean} deep 是否复制(继承)对象中的对象。
* @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);

相关文章

  • JavaScript详解使用Promise处理回调地狱的两种方法

    JavaScript详解使用Promise处理回调地狱的两种方法

    这篇文章主要介绍了JavaScript详解使用Promise处理回调地狱的两种方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-11-11
  • js实现带三角符的手风琴效果

    js实现带三角符的手风琴效果

    本文主要介绍了js实现带三角符手风琴效果的实例。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-03-03
  • 多浏览器兼容的动态加载 JavaScript 与 CSS

    多浏览器兼容的动态加载 JavaScript 与 CSS

    Omar AL Zabir这位MVP总是喜欢搞些稀奇古怪同时又很实用的小东西,并且还十分值得参考。最近他就做了一个叫做ensure的小工具用于动态加载JavaScript、CSS与HTML,而且IE、Firefox、Opera、Safari都支持了,那么我们就来看看ensure是如何做到动态加载JavaScript与CSS的。
    2008-09-09
  • 6种javascript显示当前系统时间代码

    6种javascript显示当前系统时间代码

    这篇文章主要介绍了6种javascript显示当前系统时间代码,欢迎大家学习借鉴
    2015-12-12
  • 前端实现HTML网页转PDF并导出

    前端实现HTML网页转PDF并导出

    这篇文章主要为大家详细介绍了前端如何通过html2canvas和jsPDF实现HTML网页转PDF并导出,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下
    2025-01-01
  • js判断手机端(Android手机还是iPhone手机)

    js判断手机端(Android手机还是iPhone手机)

    现在使用手机上网的人越来越多,一些下载网站会通过判断不同系统手机来访问不同网页,比如iPhone和Android。下面我们就来介绍一下如何用javascript判断iPhone或Android手机访问
    2015-07-07
  • js+FSO遍历文件夹下文件并显示

    js+FSO遍历文件夹下文件并显示

    js+FSO遍历文件夹下文件并显示...
    2007-03-03
  • 7道关于JS this的面试题,你能答对几个

    7道关于JS this的面试题,你能答对几个

    这篇文章主要给大家介绍了7道关于JS this的面试题,来看看你能答对几个,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • javascript绘制漂亮的心型线效果完整实例

    javascript绘制漂亮的心型线效果完整实例

    这篇文章主要介绍了javascript绘制漂亮的心型线效果实现方法,结合完整实例形式分析了JavaScript图形绘制的具体步骤与相关实现技巧,需要的朋友可以参考下
    2016-02-02
  • Canvas 制作动态进度加载水球详解及实例代码

    Canvas 制作动态进度加载水球详解及实例代码

    这篇文章主要介绍了Canvas 制作动态进度加载水球详解及实例代码的相关资料,这里附有实例代码及实现效果图,需要的朋友可以参考下
    2016-12-12

最新评论