惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
SecWiki News
SecWiki News
博客园_首页
人人都是产品经理
人人都是产品经理
博客园 - 聂微东
P
Palo Alto Networks Blog
V
Vulnerabilities – Threatpost
Project Zero
Project Zero
WordPress大学
WordPress大学
NISL@THU
NISL@THU
酷 壳 – CoolShell
酷 壳 – CoolShell
P
Privacy & Cybersecurity Law Blog
Jina AI
Jina AI
AWS News Blog
AWS News Blog
Scott Helme
Scott Helme
Martin Fowler
Martin Fowler
C
Cybersecurity and Infrastructure Security Agency CISA
Forbes - Security
Forbes - Security
H
Heimdal Security Blog
小众软件
小众软件
I
Intezer
A
Arctic Wolf
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
O
OpenAI News
S
Security Affairs
阮一峰的网络日志
阮一峰的网络日志
Latest news
Latest news
G
GRAHAM CLULEY
Blog — PlanetScale
Blog — PlanetScale
J
Java Code Geeks
N
News and Events Feed by Topic
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
V2EX - 技术
V2EX - 技术
Stack Overflow Blog
Stack Overflow Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
L
LINUX DO - 最新话题
博客园 - Franky
P
Proofpoint News Feed
aimingoo的专栏
aimingoo的专栏
博客园 - 司徒正美
P
Proofpoint News Feed
S
Secure Thoughts
Google DeepMind News
Google DeepMind News
Microsoft Security Blog
Microsoft Security Blog
T
The Exploit Database - CXSecurity.com
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
C
CXSECURITY Database RSS Feed - CXSecurity.com
F
Full Disclosure
Security Latest
Security Latest

博客园 - Kevin-moon

在IE中本地浏览与服务器浏览同一Html后,出现了奇异的结果 如何避免JQuery Dialog的内存泄露 JQuery另类视角-动态执行脚本的BUG 如何重构代码-简单、灵活的实现对象复制 如何重构代码-重构计划 如何重构代码-思路和方法 谈谈多线程的思维方式 简单的数据移动算法(C#) [ASP.NET MVC]-理解Routing 笑死人的十项大奖 深入APM,实现自己的APM [Windbg基础]-了解Symbols 深入线程,实现自定义的SynchronizationContext 重温ASP.NET的配置信息(简单、常用) 奇妙的SynchronizationContext 线程之间的通讯---SynchronizationContext "对象"到"山寨对象"的完整转换 我真的就只能在远方看你吗?!!! "测试驱动开发(TDD)" 动态进行"自定义公式"计算
JQuery另类视角-动态扩展对象 - Kevin-moon - 博客园
Kevin-moon · 2010-05-24 · via 博客园 - Kevin-moon

  大家都知道javascript是动态语言,它对动态的支持是与身俱来的。

  例如:有一个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对象,如下:

 

  在面向对象的编程中,对外使用的都是属性(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函数, 

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的开发者是如何设计出access函数的,让它去支持动态扩展对象,并且说明了access的执行流程。其实对于我的这种猜测不一定正确,不过不妨碍我对于JQuery的研究。