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 相关文章推荐
javascript实现的在当前窗口中漂浮框的代码
Mar 15 Javascript
jquery.messager.js插件导致页面抖动的解决方法
Jul 14 Javascript
JS创建自定义表格具体实现
Feb 11 Javascript
鼠标左键单击冲突的问题解决方法(防止冒泡)
May 14 Javascript
JS实现控制表格行内容垂直对齐的方法
Mar 30 Javascript
jQuery实现下拉框功能实例代码
May 06 Javascript
jQuery Mobile操作HTML5的常用函数总结
May 17 Javascript
jquery获取所有选中的checkbox实现代码
May 26 Javascript
全面解析JS字符串和正则表达式中的match、replace、exec等函数
Jul 01 Javascript
AngularJs $parse、$eval和$observe、$watch详解
Sep 21 Javascript
微信小程序手势操作之单触摸点与多触摸点
Mar 10 Javascript
详解element-ui动态限定的日期范围选择器代码片段
Jul 03 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中的cookie
2006/11/26 PHP
PHP内置过滤器FILTER使用实例
2014/06/25 PHP
PHP使用pear自带的mail类库发邮件的方法
2015/07/08 PHP
SAE实时日志接口SDK用法示例
2016/10/09 PHP
PHP全功能无变形图片裁剪操作类与用法示例
2017/01/10 PHP
浅谈PHP中pack、unpack的详细用法
2018/03/12 PHP
Thinkphp框架+Layui实现图片/文件上传功能分析
2020/02/07 PHP
php使用fputcsv实现大数据的导出操作详解
2020/02/27 PHP
jQuery的实现原理的模拟代码 -1 核心部分
2010/08/01 Javascript
IE的有条件注释判定IE版本详解(附实例代码)
2012/01/04 Javascript
js URL参数的拼接方法比较
2012/02/15 Javascript
js根据给定的日期计算当月有多少天实现思路及代码
2013/02/25 Javascript
自己使用jquery写的一个无缝滚动的插件
2014/04/30 Javascript
禁止iframe脚本弹出的窗口覆盖了父窗口的方法
2014/09/06 Javascript
jQuery选择器源码解读(一):Sizzle方法
2015/03/31 Javascript
聊一聊jQuery插件uploadify使用方法
2016/08/24 Javascript
js中的面向对象入门
2017/03/06 Javascript
js实现可以点击收缩或张开的悬浮窗
2017/09/18 Javascript
详解vue-router 初始化时做了什么
2018/06/11 Javascript
JavaScript设计模式之原型模式分析【ES5与ES6】
2018/07/26 Javascript
详解Angular中实现自定义组件的双向绑定的两种方法
2018/11/23 Javascript
Vue结合路由配置递归实现菜单栏功能
2020/06/16 Javascript
简单介绍Python中的len()函数的使用
2015/04/07 Python
python模拟事件触发机制详解
2018/01/19 Python
Django中create和save方法的不同
2019/08/13 Python
Python面向对象实现方法总结
2020/08/12 Python
2019年分享net面试的经历和题目
2016/08/07 面试题
设置器与访问器的定义以及各自特点
2016/01/08 面试题
关于母亲节的感言
2014/02/04 职场文书
常住证明范本
2015/06/23 职场文书
学雷锋活动简报
2015/07/20 职场文书
三严三实·严以律己心得体会
2016/01/13 职场文书
《秋天的怀念》教学反思
2016/02/17 职场文书
十二月早安励志心语大全
2019/12/03 职场文书
Python自动化之批量处理工作簿和工作表
2021/06/03 Python
springboot应用服务启动事件的监听实现
2022/04/06 Java/Android