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 相关文章推荐
文本框获得焦点和失去焦点的判断代码
Mar 18 Javascript
form表单只提交数据而不进行页面跳转的解决方案
Sep 18 Javascript
jQuery中:eq()选择器用法实例
Dec 29 Javascript
node.js集成百度UE编辑器
Feb 05 Javascript
使用C++为node.js写扩展模块
Apr 22 Javascript
js中 javascript:void(0) 用法详解
Aug 11 Javascript
JavaScript中this的四个绑定规则总结
Sep 26 Javascript
javascript的函数劫持浅析
Sep 26 Javascript
js中的DOM模拟购物车功能
Mar 22 Javascript
JS中注入eval, Function等系统函数截获动态代码
Apr 03 Javascript
微信小程序自定义navigationBar顶部导航栏适配所有机型(附完整案例)
Apr 26 Javascript
详解JavaScript作用域 闭包
Jul 29 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提交表单时判断 if($_POST[submit])与 if(isset($_POST[submit])) 的区别
2011/02/08 PHP
JQuery仿小米手机抢购页面倒计时效果
2014/12/16 Javascript
DOM基础教程之使用DOM控制表单
2015/01/20 Javascript
自定义百度分享的分享按钮
2015/03/18 Javascript
jquery实现先淡出再折叠收起的动画效果
2015/08/07 Javascript
jQuery实现鼠标滑过链接控制图片的滑动展开与隐藏效果
2015/10/28 Javascript
js实现仿微博滚动显示信息的效果
2015/12/21 Javascript
纯JS代码实现隔行变色鼠标移入高亮
2016/11/23 Javascript
详解React-Native解决键盘遮挡问题(Keyboard遮挡问题)
2017/07/13 Javascript
react-native中ListView组件点击跳转的方法示例
2017/09/30 Javascript
jQuery图片加载失败替换默认图片方法汇总
2017/11/29 jQuery
vue项目引入字体.ttf的方法
2018/09/28 Javascript
Vue源码中要const _toStr = Object.prototype.toString的原因分析
2018/12/09 Javascript
如何在vue里面优雅的解决跨域(路由冲突问题)
2019/01/20 Javascript
[43:36]Liquid vs Mineski 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
Python的另外几种语言实现
2015/01/29 Python
Python字符串和文件操作常用函数分析
2015/04/08 Python
使用Django的模版来配合字符串翻译工作
2015/07/27 Python
pandas apply 函数 实现多进程的示例讲解
2018/04/20 Python
浅析Python 实现一个自动化翻译和替换的工具
2019/04/14 Python
深入浅析python3中的unicode和bytes问题
2019/07/03 Python
python 提取文件指定列的方法示例
2019/08/07 Python
python中如何实现将数据分成训练集与测试集的方法
2019/09/13 Python
python通过opencv实现图片裁剪原理解析
2020/01/19 Python
python selenium操作cookie的实现
2020/03/18 Python
使用Python封装excel操作指南
2021/01/29 Python
麦德龙官方海外旗舰店:德国麦德龙超市
2017/12/23 全球购物
澳大利亚在线家具、灯饰和家居装饰店:LivingStyles
2018/11/20 全球购物
static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
2015/02/22 面试题
毕业生文员求职信
2013/11/03 职场文书
给交警的表扬信
2014/01/12 职场文书
公司晚会主持词
2014/03/22 职场文书
科级干部群众路线教育实践活动个人对照检查材料
2014/09/19 职场文书
结婚通知短信大全
2015/04/17 职场文书
MySQL 8.0 驱动与阿里druid版本兼容问题解决
2021/07/01 MySQL
vue报错function () { [native code] },无法出现我们想要的内容 Unknown custom element
2022/04/11 Vue.js