jQuery另类视角:动态扩展对象

开发 开发工具
本文试着从个人的角度上去猜测jQuery的开发者是如何设计出access函数的,让它去支持动态扩展对象,并且说明了access的执行流程,尽管这种猜测不一定正确,

大家都知道Javascript是动态语言,它对动态的支持是与身俱来的,jQuery作为Javascript最为流行的框架之一,同样有着这样的特性。文章将从个人的角度出发,研究jQuery的开发者是如何设计出access函数,并让它去支持动态扩展对象。

51CTO推荐专题:  jQuery从入门到精通

例如:有一个employee对象:

  1. function employee(){  
  2.     this.e_id = 0;  
  3.     this.e_name = "";  

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

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

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

  1. function dym_setprop(obj, key, value) {  
  2.     if (obj && key) {  
  3.   obj[key] = value;  
  4.     }  

看到这里,我们先让思路做个跳转,跳到C#中的employee对象,如下:

C#中的employee对象

在面向对象的编程中,对外使用的都是属性(Get/Set),那么想想如何将这种方式签入到Javascript中,现在让我们跳回dym_setprop函数内,既在dym_setprop方法中不能使用obj[key]=value的直接赋值方式,而要支持Set。

  1. function dym_setprop(obj, key, value, fn) {  
  2.     if (obj && key) {  
  3.   fn(obj, key, value);  
  4.     }  

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

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

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

  1. function dym_setprop(obj, key, value, fn, exec, pass) {  
  2.     if (obj && key) {  
  3.   var temp = value;  
  4.   if (exec) {  
  5. temp = value.call(obj, key, fn(obj, key));  
  6.   }  
  7.   fn(obj, key, temp, pass);  
  8.     }  

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

  1. employee.AccessProp = function(obj, key, value) {  
  2.     if (value) {  
  3.   obj[key] = value;  
  4.     }  
  5.     else {  
  6.   return obj[key];  
  7.     }  
  8. }  
  9. 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函数,

  1. function access( elems, key, value, exec, fn, pass ) {  
  2.     var length = elems.length;  
  3.       
  4.     // Setting many attributes  
  5.     if ( typeof key === "object" ) {  
  6.   for ( var k in key ) {  
  7. access( elems, k, key[k], exec, fn, value );  
  8.   }  
  9.   return elems;  
  10.     }  
  11.       
  12.     // Setting one attribute  
  13.     if ( value !== undefined ) {  
  14.   // Optionally, function values get executed if exec is true  
  15.   exec = !pass && exec && jQuery.isFunction(value);  
  16.     
  17.   for ( var i = 0; i < length; i++ ) {  
  18. fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );  
  19.   }  
  20.     
  21.   return elems;  
  22.     }  
  23.       
  24.     // Getting an attribute  
  25.     return length ? fn( elems[0], key ) : null;  

仔细看完access函数的代码,你一定发现它和dym_setprop的相试度很高,它只是多了一段代码:

  1. if ( typeof key === "object" ) {  
  2.    for ( var k in key ) {  
  3.     access( elems, k, key[k], exec, fn, value );  
  4.    }  
  5.    return elems;  

很容易看出它其实就是用来支持object对象的动态扩展属性。具体的执行流程通过下图来展示:

执行流程图

到这里已经写完了,本文试着从自己的角度上去猜测jQuery的开发者是如何设计出access函数的,让它去支持动态扩展对象,并且说明了access的执行流程。其实对于我的这种猜测不一定正确,不过不妨碍我对于jQuery的研究。

文章转自Kevin-moon的博客,

原文地址:http://www.cnblogs.com/Kevin-moon/archive/2010/05/24/1742693.html

【编辑推荐】

  1. 5种方法教你用jQuery重写表单验证
  2. 你应该学习jQuery的七大理由
  3. 了解jQuery技巧来提高你的代码质量
  4. 10个自由丰富的jQuery或JavaScript编辑器
  5. 阐述jQuery工具函数的使用和解决方案
责任编辑:王晓东 来源: 博客园
相关推荐

2011-12-29 09:24:54

iOS应用下载排行榜

2009-09-09 16:06:08

对象

2013-12-02 14:18:33

jQuery对象

2015-09-24 08:54:36

java动态代理

2015-09-24 08:55:14

Java动态代理扩展

2020-03-10 18:53:16

移动支付另类支付APP

2011-08-22 16:19:58

jQuery

2023-09-07 14:03:41

5GXR

2012-06-15 17:50:26

2010-04-21 09:26:54

Java动态代理

2021-06-30 09:40:31

MySQL数据库Java

2012-02-07 10:05:40

jQuery MobijQuery Mobi

2009-07-24 11:01:12

jQuery框架

2009-09-03 17:18:40

C#扩展性对象模型

2009-11-25 10:16:49

linuxphpizePHP

2015-08-18 13:25:12

PaaS服务架构动态扩展

2010-09-01 08:57:27

jQueryDOM对象

2015-03-13 09:30:23

iOS内存管理

2021-01-07 14:10:42

开发运维软件

2009-05-19 14:13:46

.NET反射Assembly
点赞
收藏

51CTO技术栈公众号