神乎奇技的jQuery Hacking

十八歲的jQuery天才少年James Padolsey這回又讓我佩服到起了雞皮疙瘩...

一直以來,jQuery的語法有個小缺陷,就是在API中少了直接引用自己的捷徑。舉個例子來說,如果我想讓某個<div id='”dvX”>的寬度增加20px,常見的解法有兩種:

  1. $("#dvX”).width($(“#dvX”).width() + 20); <--會引用兩次$(...),效能不佳
  2. var $d = $(“#dvX”); $d.width($d.width()); <-- 效能較佳,但還是囉嗦

James在他的Blog文章中,發明了一種新寫法:

$("#dvX”).width($._this.width() + 20);

James的做法是巧妙地攔截jQuery建構式,偷偷地把最後一次呼叫的jQuery建構式內容用jQuery._this共用變數保存下來: (有一點以前寫組合語言攔截INT中斷的fu~~~)

(function(_jQueryInit){
     jQuery.fn.init = function(selector, context) {
        return (jQuery._this = new _jQueryInit(selector, context));
    };
})(jQuery.fn.init);

Javascript的超大彈性與天才少年的慧黠,一樣都教人嘆為觀止,目瞪口呆!

Published 30 June 2009 12:04 AM 由 Jeffrey
Filed under:


意見

# Ammon said on 29 June, 2009 07:24 PM

以相對於自身來說,我是希望能有類似下面這樣的寫法

$('#dvX').width('+',20);  // not support yet

$('#dvX').width('+=20'); // not support yet

可以偷偷的用這樣代替XD

$('#dvX').animate({width:'+=20'},0); // not really good

但是如原文中要用到 parent 來做運算就沒辦法了

原文的目的是要拿到最後一次select的jquery物件來在後面串接的參數中使用

# boho said on 29 June, 2009 09:44 PM

$('#dvX').width($(this).width()+20);

怎么样?也是同样的效果?

# Phoenix said on 30 June, 2009 09:47 AM

很漂亮的解法0.0

在想可不可以解決這個,

result.children(".ui-datepicker-year").html(result.children(".ui-datepicker-year").html() + "年");

改成

result.children(".ui-datepicker-year").html($._this.html() + "年");

# Ark said on 30 June, 2009 10:54 AM

效能是吧~不用花俏~更直覺的攔截

with ($(".dvx")) { width(width() +20) }

with(result.children(".ui-datepicker-year")){

html(html()+"年").width(width() +20);//愛連就繼續連

height(height()+50);//愛分行就分行看

}

# Jeffrey said on 30 June, 2009 02:35 PM

to Ark, with這招很好很強大!!!(筆記,沙沙沙...) 沒想到Javascript還有這招可用,大推!! 唯一會被挑剔的應該是如此就沒法讓jQuery一路串接下去。

# pbnttttt said on 30 June, 2009 08:17 PM

為了可以串接~但實不實用我不清楚@@~For Fun

(function(Jobj) { with (Jobj) { width(width() + 20); } return Jobj; })($("#dvX")).text(new Date().toTimeString());

# pbnttttt said on 30 June, 2009 08:34 PM

有人提出with效能不好去查了一下~把with那段改成Jobj.width(Jobj.width() + 20);其實就跟黑暗大提出的解法2沒什麼差別吧!!

微軟提出的js效能建議,最後一點有提到避免使用with喔

blogs.msdn.com/.../728654.aspx

# Ark said on 01 July, 2009 01:45 AM

嘿~很弱小....寫程式的龜毛人通常會出現的共同盲點

那就是.....越短越強大(和某方面需求不同)

避免使用with也是要看程式的需求

如說程式內包有大量的loop操弄某一obj,用了with可以捨去許多的"."

這時以js特性多一點 "." 就多噸一絲絲

效能就值得了,若寫成with包with或是寫成loop包到with外層

那就是老耿中的老耿嚕

其實可以觀看Jqurery1.26與1.32

1.26只出現過一次 if ( elem ) with ( jQuery.browser ) {OOXX... 到了1.32就完全消失了, 可見被大量引用的$字

對with的拔除產生的效能增加

...可是...可是...人家喜歡短昧

# streaker blog said on 01 July, 2009 09:49 PM

    人小,但大智慧

# lucas said on 02 July, 2009 09:08 PM

大推 增長見聞

# Tony said on 17 September, 2009 11:40 AM

Ark,

給你拍拍手

# showP said on 25 November, 2009 08:44 PM

各位好,小弟是上星期五才開始接觸 JQuery

JQuery 真是一個厲害的東西

我寫了幾個範例後,也有發現我也有這樣的困擾

所以我想了一下是否也可以這樣寫(小弟是新手 , 如果有任何效能、觀念問題,請大家多多指教,謝謝)

$("#dvX")

   .alias("current") // 將目前 reference 的 jQuery 物件 快取起來

   .width($.alias("current").width() + 20) // 取得快取物件

   .endAlias();  // 移除 所有快取到的 jQuery 物件

這樣寫的好處是可以有多個 alias  , 例如以下的範例 , 且還是可以支援串接

$("#dvX")

   .find("#idA").alias("a").end()

   .find("#idB").alias("b").end()

   .width( $.alias("a").width()  + $.alias("b").width() )

   .endAlias();

jQuery.fn.alias = function(name) {

   if ( ! jQuery._jQueryRef ) jQuery._jQueryRef = {};

       var _JQuery = jQuery._jQueryRef[name];

if( ! _JQuery ) {

           jQuery._jQueryRef[name] = this;

           _JQuery = this;

}

   return _JQuery

}

jQuery.fn.endAlias = function() {

   delete jQuery._jQueryRef;

   return this;

}

jQuery.alias = jQuery.fn.alias;

# Jeffrey said on 25 November, 2009 10:12 PM

to showP, 這點子很棒,給你拍拍手... 我還想到可以借用jQuery.data, jQuery.removeData省下自己管理alias名稱集合的功夫

# showP said on 25 November, 2009 11:21 PM

Jeffrey  你好

再想請問一下

我寫的範例中 , 如果不加上 endAlias() , 是否會產生記憶體無法釋放的問題呢?

另外你提到的 jQuery.data 這個要怎麼用?,因為 jQuery.data 不是會一定要 binding 在一個 jQuery collection 上嗎? (docs.jquery.com/.../data) , 如果我搞混了..是否有一些範例呢?

謝謝你

# Jeffrey said on 26 November, 2009 10:16 AM

to showP, 我會跟選擇bind在document.body上,$(document.body).data("blah", ...). 至於釋放記憶體的議題,我曾胡亂做過一些測試,但沒有具體的結論,但我想有釋放肯定勝過留下攤子讓Javascript Engine自行料理。

# showP said on 26 November, 2009 11:03 PM

Jeffrey  好

真是一語點醒夢中人啊~~

套用你的話 (筆記,沙沙沙...)

謝謝~

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 

請輸入以上的數字:

搜尋

Go

<June 2009>
SunMonTueWedThuFriSat
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011
 
RSS
【工商服務】
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


BlogLook Score and Rank

Syndication