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 相关文章推荐
创建公共调用 jQuery Ajax 带返回值
Aug 01 Javascript
json对象转字符串如何实现
Dec 02 Javascript
XMLHttpRequest处理xml格式的返回数据(示例代码)
Nov 21 Javascript
jQuery实现滑动页面固定顶部显示(可根据显示位置消失与替换)
Oct 28 Javascript
js实现内容显示并使用json传输数据
Mar 16 Javascript
jQuery+正则+文本框只能输入数字的实现方法
Oct 07 Javascript
js+html5生成自动排列对话框实例
Oct 09 Javascript
vue中父子组件注意事项,传值及slot应用技巧
May 09 Javascript
JS插件clipboard.js实现一键复制粘贴功能
Dec 04 Javascript
服务端预渲染之Nuxt(使用篇)
Apr 08 Javascript
JS实现选项卡效果的代码实例
May 20 Javascript
js如何验证密码强度
Mar 18 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
PHP常用函数和常见疑难问题解答
2014/03/05 PHP
php unlink()函数使用教程
2018/07/12 PHP
javascript 操作Word和Excel的实现代码
2009/10/26 Javascript
js 与或运算符 || &amp;&amp; 妙用
2009/12/09 Javascript
jquery实现图片等比例缩放以及max-width在ie中不兼容解决
2013/03/21 Javascript
js去除空格的12种实用方法
2013/11/08 Javascript
js计算德州扑克牌面值的方法
2015/03/04 Javascript
如何根据百度地图计算出两地之间的驾驶距离(两种语言js和C#)
2015/10/29 Javascript
jQuery树形插件jquery.simpleTree.js用法分析
2016/09/05 Javascript
jQuery检查元素存在性(推荐)
2016/09/17 Javascript
JavaScript中object和Object的区别(详解)
2017/02/27 Javascript
十分钟带你快速了解React16新特性
2017/11/10 Javascript
Phaser.js实现简单的跑酷游戏附源码下载
2018/10/26 Javascript
详解JavaScript栈内存与堆内存
2019/04/04 Javascript
vue路由切换时取消之前的所有请求操作
2020/09/01 Javascript
js实现验证码干扰(静态)
2021/02/22 Javascript
[03:11]DOTA2上海特锦赛小组赛第一日recap精彩回顾
2016/02/28 DOTA
python 多线程应用介绍
2012/12/19 Python
python通过ElementTree操作XML获取结点读取属性美化XML
2013/12/02 Python
Python中Django框架利用url来控制登录的方法
2015/07/25 Python
python中栈的原理及实现方法示例
2019/11/27 Python
python实现的Iou与Giou代码
2020/01/18 Python
python+selenium+chrome批量文件下载并自动创建文件夹实例
2020/04/27 Python
Rockport乐步美国官网:风靡美国的白宫鞋
2016/11/24 全球购物
Mytheresa美国官网:德国知名的女性奢侈品电商
2017/05/27 全球购物
Bodum官网:咖啡和茶壶、玻璃器皿、厨房电器等
2018/08/01 全球购物
main 函数执行以前,还会执行什么代码
2013/04/17 面试题
银行出纳岗位职责
2013/11/25 职场文书
大学生就业意向书范文
2014/04/01 职场文书
社区科普工作方案
2014/06/03 职场文书
婚前协议书范本两则
2014/10/16 职场文书
金秋助学感谢信
2015/01/21 职场文书
高中团支书竞选稿
2015/11/21 职场文书
巧用 -webkit-box-reflect 倒影实现各类动效(小结)
2021/04/22 HTML / CSS
浅谈Python3中datetime不同时区转换介绍与踩坑
2021/08/02 Python
前端监听websocket消息并实时弹出(实例代码)
2021/11/27 Javascript