JQuery 動態(tài)擴(kuò)展對象之另類視角
更新時間:2010年05月25日 23:33:02 作者:
大家都知道javascript是動態(tài)語言,它對動態(tài)的支持是與身俱來的。
例如:有一個employee對象,
function employee(){
this.e_id = 0;
this.e_name = "";
}
現(xiàn)在需要為它動態(tài)的新增"age"屬性和"toString()"方法,
var empObj = new employee();
empObj["age"] = 20;
empObj["toString"] = function() { return this.e_id.toString() + this.e_name; };
一行簡單的代碼就承擔(dān)了這項工作,這是Javascript內(nèi)置支持的,不過往往我們需要在這基礎(chǔ)上支持一定程度的擴(kuò)展,所以會將這一行簡單的代碼抽成一個方法:
function dym_setprop(obj, key, value) {
if (obj && key) {
obj[key] = value;
}
}
看到這里,我們先讓思路做個跳轉(zhuǎn),跳到C#中的employee對象,如下:

在面向?qū)ο蟮木幊讨?,對外使用的都是屬性(Get/Set),那么想想如何將這種方式簽入到Javascript中,現(xiàn)在讓我們跳回dym_setprop函數(shù)內(nèi),既在dym_setprop方法中不能使用obj[key]=value的直接賦值方式,而要支持Set。
function dym_setprop(obj, key, value, fn) {
if (obj && key) {
fn(obj, key, value);
}
}
參數(shù)fn,在dym_setprop中不直接操作任何對象,使用函數(shù)fn來代替相應(yīng)的操作代碼,則在這里除了支持Set外,還有其他很大的自由空間。
讓我們繼續(xù)深入dym_setprop方法,現(xiàn)在我們把關(guān)注點放在參數(shù)value上,大家都清楚value可以是值類型,也可以是函數(shù),對于值類型來說,不用考慮其他東西直接賦值就可以了,對于函數(shù)來說就沒有這么簡單,它支持兩種操作:
1、直接將函數(shù)賦給新擴(kuò)展的屬性
2、將函數(shù)執(zhí)行的返回值賦給新擴(kuò)展的屬性
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);
}
}
在這段代碼中參數(shù)exec充當(dāng)了上面兩種操作選擇的角色,參數(shù)pass是一個額外的執(zhí)行參數(shù)。除此之外,大家也許會對fn有些疑惑,因為上面有兩個地方使用了,區(qū)別只有參數(shù)個數(shù)不同,fn到底代表什么?!再次想下C#中的屬性,它是有Get/Set的,那么在這里fn(obj,key)就相當(dāng)與Get,而fn(obj,key,temp,pass)就相當(dāng)與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);
看了這么多,也許大家覺得郁悶,簡單的動態(tài)擴(kuò)展對象程序為什么要以這種方式來編寫,有種沒事找事的感覺,其實不然,如果你只想做動態(tài)擴(kuò)展對象,那么我建議你別采用上述dym_setprop的思路,但是如果你想從更加抽象的角度上思考,將dym_setprop內(nèi)的程序作為一個流程執(zhí)行的模板,那么這是一個不錯的方式,因為dym_setprop內(nèi)部不承擔(dān)任何具體代碼(obj[key]=value或obj[key])的執(zhí)行,它都通過函數(shù)fn來代替,這樣對于具體執(zhí)行來說有完全自由的空間。
理解完上述的思路后,讓我們進(jìn)入本文的核心,JQuery是如何實現(xiàn)動態(tài)擴(kuò)展對象的?access函數(shù),
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;
}
仔細(xì)看完access函數(shù)的代碼,你一定發(fā)現(xiàn)它和dym_setprop的相試度很高,它只是多了一段代碼:
if ( typeof key === "object" ) {
for ( var k in key ) {
access( elems, k, key[k], exec, fn, value );
}
return elems;
}
很容易看出它其實就是用來支持object對象的動態(tài)擴(kuò)展屬性。具體的執(zhí)行流程通過下圖來展示:

到這里已經(jīng)寫完了,本文試著從自己的角度上去猜測JQuery的開發(fā)者是如何設(shè)計出access函數(shù)的,讓它去支持動態(tài)擴(kuò)展對象,并且說明了access的執(zhí)行流程。其實對于我的這種猜測不一定正確,不過不妨礙我對于JQuery的研究。
復(fù)制代碼 代碼如下:
function employee(){
this.e_id = 0;
this.e_name = "";
}
現(xiàn)在需要為它動態(tài)的新增"age"屬性和"toString()"方法,
復(fù)制代碼 代碼如下:
var empObj = new employee();
empObj["age"] = 20;
empObj["toString"] = function() { return this.e_id.toString() + this.e_name; };
一行簡單的代碼就承擔(dān)了這項工作,這是Javascript內(nèi)置支持的,不過往往我們需要在這基礎(chǔ)上支持一定程度的擴(kuò)展,所以會將這一行簡單的代碼抽成一個方法:
復(fù)制代碼 代碼如下:
function dym_setprop(obj, key, value) {
if (obj && key) {
obj[key] = value;
}
}
看到這里,我們先讓思路做個跳轉(zhuǎn),跳到C#中的employee對象,如下:

在面向?qū)ο蟮木幊讨?,對外使用的都是屬性(Get/Set),那么想想如何將這種方式簽入到Javascript中,現(xiàn)在讓我們跳回dym_setprop函數(shù)內(nèi),既在dym_setprop方法中不能使用obj[key]=value的直接賦值方式,而要支持Set。
復(fù)制代碼 代碼如下:
function dym_setprop(obj, key, value, fn) {
if (obj && key) {
fn(obj, key, value);
}
}
參數(shù)fn,在dym_setprop中不直接操作任何對象,使用函數(shù)fn來代替相應(yīng)的操作代碼,則在這里除了支持Set外,還有其他很大的自由空間。
讓我們繼續(xù)深入dym_setprop方法,現(xiàn)在我們把關(guān)注點放在參數(shù)value上,大家都清楚value可以是值類型,也可以是函數(shù),對于值類型來說,不用考慮其他東西直接賦值就可以了,對于函數(shù)來說就沒有這么簡單,它支持兩種操作:
1、直接將函數(shù)賦給新擴(kuò)展的屬性
2、將函數(shù)執(zhí)行的返回值賦給新擴(kuò)展的屬性
復(fù)制代碼 代碼如下:
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);
}
}
在這段代碼中參數(shù)exec充當(dāng)了上面兩種操作選擇的角色,參數(shù)pass是一個額外的執(zhí)行參數(shù)。除此之外,大家也許會對fn有些疑惑,因為上面有兩個地方使用了,區(qū)別只有參數(shù)個數(shù)不同,fn到底代表什么?!再次想下C#中的屬性,它是有Get/Set的,那么在這里fn(obj,key)就相當(dāng)與Get,而fn(obj,key,temp,pass)就相當(dāng)與Set。
例如:看下面的代碼,對于fn的定義與使用,
復(fù)制代碼 代碼如下:
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);
看了這么多,也許大家覺得郁悶,簡單的動態(tài)擴(kuò)展對象程序為什么要以這種方式來編寫,有種沒事找事的感覺,其實不然,如果你只想做動態(tài)擴(kuò)展對象,那么我建議你別采用上述dym_setprop的思路,但是如果你想從更加抽象的角度上思考,將dym_setprop內(nèi)的程序作為一個流程執(zhí)行的模板,那么這是一個不錯的方式,因為dym_setprop內(nèi)部不承擔(dān)任何具體代碼(obj[key]=value或obj[key])的執(zhí)行,它都通過函數(shù)fn來代替,這樣對于具體執(zhí)行來說有完全自由的空間。
理解完上述的思路后,讓我們進(jìn)入本文的核心,JQuery是如何實現(xiàn)動態(tài)擴(kuò)展對象的?access函數(shù),
復(fù)制代碼 代碼如下:
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;
}
仔細(xì)看完access函數(shù)的代碼,你一定發(fā)現(xiàn)它和dym_setprop的相試度很高,它只是多了一段代碼:
復(fù)制代碼 代碼如下:
if ( typeof key === "object" ) {
for ( var k in key ) {
access( elems, k, key[k], exec, fn, value );
}
return elems;
}
很容易看出它其實就是用來支持object對象的動態(tài)擴(kuò)展屬性。具體的執(zhí)行流程通過下圖來展示:

到這里已經(jīng)寫完了,本文試著從自己的角度上去猜測JQuery的開發(fā)者是如何設(shè)計出access函數(shù)的,讓它去支持動態(tài)擴(kuò)展對象,并且說明了access的執(zhí)行流程。其實對于我的這種猜測不一定正確,不過不妨礙我對于JQuery的研究。
您可能感興趣的文章:
- 原生js實現(xiàn)復(fù)制對象、擴(kuò)展對象 類似jquery中的extend()方法
- 淺談jQuery中的$.extend方法來擴(kuò)展JSON對象
- 基于jQuery的一個擴(kuò)展form序列化到j(luò)son對象
- 模仿JQuery.extend函數(shù)擴(kuò)展自己對象的js代碼
- 擴(kuò)展jQuery對象時如何擴(kuò)展成員變量具體怎么實現(xiàn)
- jQuery.extend()、jQuery.fn.extend()擴(kuò)展方法示例詳解
- Jquery 的擴(kuò)展方法總結(jié)
- Jquery中擴(kuò)展方法extend使用技巧
- 修改或擴(kuò)展jQuery原生方法的代碼實例
- JavaScript自執(zhí)行函數(shù)和jQuery擴(kuò)展方法詳解
- JQuery擴(kuò)展對象方法操作示例
相關(guān)文章
Jquery節(jié)點遍歷next與nextAll方法使用示例
next()方法用于獲取“節(jié)點之后”挨著它的第一個“同類同輩”元素。nextAll()方法用于獲取“節(jié)點之后”所有的元素2014-07-07jQuery ajax調(diào)用后臺aspx后臺文件的兩種常見方法(不是ashx)
這篇文章主要介紹了jQuery ajax調(diào)用后臺aspx后臺文件的兩種常見方法(不是ashx)的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-06-06jQuery實現(xiàn)仿Google首頁拖動效果的方法
這篇文章主要介紹了jQuery實現(xiàn)仿Google首頁拖動效果的方法,涉及jQuery操作鼠標(biāo)事件及div層的相關(guān)技巧,非常具有實用價值,需要的朋友可以參考下2015-05-05動態(tài)調(diào)用css文件——jquery的應(yīng)用
這篇文章主要介紹了動態(tài)調(diào)用css文件——jquery的應(yīng)用2007-02-02