JQuery 动态扩展对象之另类视角


Posted in Javascript onMay 25, 2010

例如:有一个employee对象,

function employee(){ 
this.e_id = 0; 
this.e_name = ""; 
}

现在需要为它动态的新增"age"属性和"toString()"方法,

var empObj = new employee(); 
empObj["age"] = 20; 
empObj["toString"] = function() { return this.e_id.toString() + this.e_name; };

一行简单的代码就承担了这项工作,这是Javascript内置支持的,不过往往我们需要在这基础上支持一定程度的扩展,所以会将这一行简单的代码抽成一个方法:

function dym_setprop(obj, key, value) { 
if (obj && key) { 
obj[key] = value; 
} 
}

看到这里,我们先让思路做个跳转,跳到C#中的employee对象,如下:
JQuery 动态扩展对象之另类视角
在面向对象的编程中,对外使用的都是属性(Get/Set),那么想想如何将这种方式签入到Javascript中,现在让我们跳回dym_setprop函数内,既在dym_setprop方法中不能使用obj[key]=value的直接赋值方式,而要支持Set。

function dym_setprop(obj, key, value, fn) { 
if (obj && key) { 
fn(obj, key, value); 
} 
}

参数fn,在dym_setprop中不直接操作任何对象,使用函数fn来代替相应的操作代码,则在这里除了支持Set外,还有其他很大的自由空间。
让我们继续深入dym_setprop方法,现在我们把关注点放在参数value上,大家都清楚value可以是值类型,也可以是函数,对于值类型来说,不用考虑其他东西直接赋值就可以了,对于函数来说就没有这么简单,它支持两种操作:

1、直接将函数赋给新扩展的属性

2、将函数执行的返回值赋给新扩展的属性

function dym_setprop(obj, key, value, fn, exec, pass) { 
if (obj && key) { 
var temp = value; 
if (exec) { 
temp = value.call(obj, key, fn(obj, key)); 
} 
fn(obj, key, temp, pass); 
} 
}

在这段代码中参数exec充当了上面两种操作选择的角色,参数pass是一个额外的执行参数。除此之外,大家也许会对fn有些疑惑,因为上面有两个地方使用了,区别只有参数个数不同,fn到底代表什么?!再次想下C#中的属性,它是有Get/Set的,那么在这里fn(obj,key)就相当与Get,而fn(obj,key,temp,pass)就相当与Set。

例如:看下面的代码,对于fn的定义与使用,

employee.AccessProp = function(obj, key, value) { 
if (value) { 
obj[key] = value; 
} 
else { 
return obj[key]; 
} 
} dym_setprop(empObj, "age", function(key, value) { return value + 10; }, employee.AccessProp, true);

看了这么多,也许大家觉得郁闷,简单的动态扩展对象程序为什么要以这种方式来编写,有种没事找事的感觉,其实不然,如果你只想做动态扩展对象,那么我建议你别采用上述dym_setprop的思路,但是如果你想从更加抽象的角度上思考,将dym_setprop内的程序作为一个流程执行的模板,那么这是一个不错的方式,因为dym_setprop内部不承担任何具体代码(obj[key]=value或obj[key])的执行,它都通过函数fn来代替,这样对于具体执行来说有完全自由的空间。

理解完上述的思路后,让我们进入本文的核心,JQuery是如何实现动态扩展对象的?access函数,

function access( elems, key, value, exec, fn, pass ) { 
var length = elems.length; // Setting many attributes 
if ( typeof key === "object" ) { 
for ( var k in key ) { 
access( elems, k, key[k], exec, fn, value ); 
} 
return elems; 
} 
// Setting one attribute 
if ( value !== undefined ) { 
// Optionally, function values get executed if exec is true 
exec = !pass && exec && jQuery.isFunction(value); 
for ( var i = 0; i < length; i++ ) { 
fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); 
} 
return elems; 
} 
// Getting an attribute 
return length ? fn( elems[0], key ) : null; 
}

仔细看完access函数的代码,你一定发现它和dym_setprop的相试度很高,它只是多了一段代码:
if ( typeof key === "object" ) { 
for ( var k in key ) { 
access( elems, k, key[k], exec, fn, value ); 
} 
return elems; 
}

很容易看出它其实就是用来支持object对象的动态扩展属性。具体的执行流程通过下图来展示:
JQuery 动态扩展对象之另类视角
到这里已经写完了,本文试着从自己的角度上去猜测JQuery的开发者是如何设计出access函数的,让它去支持动态扩展对象,并且说明了access的执行流程。其实对于我的这种猜测不一定正确,不过不妨碍我对于JQuery的研究。
Javascript 相关文章推荐
js split 的用法和定义 js split分割字符串成数组的实例代码
May 13 Javascript
Javascript 面向对象(三)接口代码
May 23 Javascript
jquery.mobile 共同布局遇到的问题小结
Feb 10 Javascript
iScroll中事件点击触发两次解决方案
Mar 11 Javascript
JS中call/apply、arguments、undefined/null方法详解
Feb 15 Javascript
使用Javascript实现选择下拉菜单互移并排序
Feb 23 Javascript
jquery输入数字随机抽奖特效的简单实现代码
Jun 10 Javascript
jQuery实现倒计时(倒计时年月日可自己输入)
Dec 02 Javascript
深入理解vue-router之keep-alive
Aug 31 Javascript
three.js实现3D影院的原理的代码分析
Dec 18 Javascript
vue addRoutes实现动态权限路由菜单的示例
May 15 Javascript
Vue组件模板及组件互相引用代码实例
Mar 11 Javascript
jQuery的Ajax时无响应数据的解决方法
May 25 #Javascript
JavaScript操作XML实例代码(获取新闻标题并分页,并分页)
May 25 #Javascript
ExtJS 2.0 GridPanel基本表格简明教程
May 25 #Javascript
Chrome中模态对话框showModalDialog返回值问题的解决方法
May 25 #Javascript
json格式化/压缩工具 Chrome插件扩展版
May 25 #Javascript
js 多种变量定义(对象直接量,数组直接量和函数直接量)
May 24 #Javascript
js 设置选中行的样式的实现代码
May 24 #Javascript
You might like
php mssql扩展SQL查询中文字段名解决方法
2012/10/15 PHP
CI框架源码解读之URI.php中_fetch_uri_string()函数用法分析
2016/05/18 PHP
laravel利用中间件做防非法登录和权限控制示例
2019/10/21 PHP
PHP CURL实现模拟登陆并上传文件操作示例
2020/01/02 PHP
jquery实现通用版鼠标经过淡入淡出效果
2014/06/15 Javascript
简单谈谈Javascript中类型的判断
2015/10/19 Javascript
详解Angularjs中的依赖注入
2016/03/11 Javascript
深入理解AngularJS中的ng-bind-html指令和$sce服务
2016/09/08 Javascript
HTML5+Canvas调用手机拍照功能实现图片上传(上)
2017/04/21 Javascript
JS传播事件、取消事件默认行为、阻止事件传播详解
2017/08/14 Javascript
JS倒计时实例_天时分秒
2017/08/22 Javascript
Vue精简版风格概述
2018/01/30 Javascript
详解Vue微信授权登录前后端分离较为优雅的解决方案
2018/06/29 Javascript
JavaScript选择排序算法原理与实现方法示例
2018/08/06 Javascript
关于JavaScript 数组你应该知道的事情(推荐)
2019/04/10 Javascript
JS实现点击下拉列表文本框中出现对应的网址,点击跳转按钮实现跳转
2019/11/25 Javascript
jQuery单页面文字搜索插件jquery.fullsearch.js的使用方法
2020/02/04 jQuery
JavaScript实现4位随机验证码的生成
2021/01/28 Javascript
[01:33:30]DOTA2-DPC中国联赛 正赛 RNG vs Phoenix BO3 第二场 2月5日
2021/03/11 DOTA
[08:08]DOTA2-DPC中国联赛2月28日Recap集锦
2021/03/11 DOTA
python中pycurl库的用法实例
2014/09/30 Python
python3.5使用tkinter制作记事本
2016/06/20 Python
Python实现的文本简单可逆加密算法示例
2017/05/18 Python
Python爬虫实例_利用百度地图API批量获取城市所有的POI点
2018/01/10 Python
python处理“
2019/06/10 Python
解决python图像处理图像赋值后变为白色的问题
2020/06/04 Python
python使用建议与技巧分享(二)
2020/08/17 Python
python开发入门——列表生成式
2020/09/03 Python
请用Python写一个获取用户输入数字,并根据数字大小输出不同信息的脚本
2014/05/20 面试题
小班秋游活动方案
2014/02/22 职场文书
安全承诺书格式
2014/05/21 职场文书
个人先进事迹材料
2014/12/29 职场文书
幼师个人总结范文
2015/02/28 职场文书
欢送领导祝酒词
2015/08/12 职场文书
Python绘制分类图的方法
2021/04/20 Python
Windows Server 2019 域控制器安装图文教程
2022/04/28 Servers