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


Posted in Javascript onDecember 02, 2009

通常在函数里面给了参数对象的默认值,这个时候就需要通过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 相关文章推荐
FLASH 广告之外的链接
Dec 16 Javascript
简单时间提示DEMO从0开始一直进行计时
Nov 19 Javascript
JavaScript中join()方法的使用简介
Jun 09 Javascript
javaScript 事件绑定、事件冒泡、事件捕获和事件执行顺序整理总结
Oct 10 Javascript
学习Node.js模块机制
Oct 17 Javascript
JS实现的简易拖放效果示例
Dec 29 Javascript
JavaScript基于扩展String实现替换字符串中index处字符的方法
Jun 13 Javascript
Angular4实现鼠标悬停3d倾斜效果
Oct 25 Javascript
浅谈vue自定义全局组件并通过全局方法 Vue.use() 使用该组件
Dec 07 Javascript
vue写一个组件
Apr 09 Javascript
JS中实现隐藏部分姓名或者电话号码的代码
Jul 17 Javascript
angular.js实现列表orderby排序的方法
Oct 02 Javascript
JS类的封装及实现代码
Dec 02 #Javascript
Jquery选择器 $实现原理
Dec 02 #Javascript
js 表格隔行颜色
Dec 02 #Javascript
让FireFox支持innerText的实现代码
Dec 01 #Javascript
JavaScript 直接操作本地文件的实现代码
Dec 01 #Javascript
js 变量类型转换常用函数与代码[比较全]
Dec 01 #Javascript
Jquery 快速构建可拖曳的购物车DragDrop
Nov 30 #Javascript
You might like
zf框架db类的分页示例分享
2014/03/14 PHP
TP5框架实现自定义分页样式的方法示例
2020/04/05 PHP
jQuery随便控制任意div隐藏的方法
2013/06/28 Javascript
javascript写的异步加载js文件函数(支持数组传参)
2014/06/07 Javascript
浅谈jQuery异步对象(XMLHttpRequest)
2014/11/17 Javascript
Node.js的包详细介绍
2015/01/14 Javascript
jQuery根据用户电脑是mac还是pc加载对应样式的方法
2015/06/26 Javascript
你不知道的高性能JAVASCRIPT
2016/01/18 Javascript
JS实现的在线调色板实例(附demo源码下载)
2016/03/01 Javascript
jQuery ajax全局函数处理session过期后的ajax跳转问题
2016/06/03 Javascript
基于Node.js + WebSocket打造即时聊天程序嗨聊
2016/11/29 Javascript
vue实现全选、反选功能
2020/11/17 Javascript
原生js基于canvas实现一个简单的前端截图工具代码实例
2019/09/10 Javascript
微信小程序wx.getUserInfo授权获取用户信息(头像、昵称)的实现
2020/08/19 Javascript
[03:42]2014DOTA2西雅图国际邀请赛7月9日TOPPLAY
2014/07/09 DOTA
python下函数参数的传递(参数带星号的说明)
2010/09/19 Python
python模块restful使用方法实例
2013/12/10 Python
Python实现获取操作系统版本信息方法
2015/04/08 Python
Python字符串详细介绍
2015/05/09 Python
Python每天必学之bytes字节
2016/01/28 Python
Unicode和Python的中文处理
2017/03/19 Python
好的Python培训机构应该具备哪些条件
2018/05/23 Python
初探利用Python进行图文识别(OCR)
2019/02/26 Python
python3实现钉钉消息推送的方法示例
2019/03/14 Python
Python3.5装饰器原理及应用实例详解
2019/04/30 Python
pytorch 实现模型不同层设置不同的学习率方式
2020/01/06 Python
Expedia丹麦:全球领先的旅游网站
2018/03/18 全球购物
禁止高声喧哗的标语
2014/06/11 职场文书
幼儿园标语大全
2014/06/19 职场文书
股东授权委托书范本
2014/09/13 职场文书
学校领导干部民主生活会整改方案
2014/09/29 职场文书
2014年纪检监察工作总结
2014/11/11 职场文书
2019毕业论文致谢词
2019/06/24 职场文书
python文本处理的方案(结巴分词并去除符号)
2021/05/26 Python
数据库之SQL技巧整理案例
2021/07/07 SQL Server
CSS的calc函数用法小结
2022/06/25 HTML / CSS