十八歲的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的超大彈性與天才少年的慧黠,一樣都教人嘆為觀止,目瞪口呆!


Comments

# by Ammon

以相對於自身來說,我是希望能有類似下面這樣的寫法 $('#dvX').width('+',20); // not support yet $('#dvX').width('+=20'); // not support yet 可以偷偷的用這樣代替XD $('#dvX').animate({width:'+=20'},0); // not really good 但是如原文中要用到 parent 來做運算就沒辦法了 原文的目的是要拿到最後一次select的jquery物件來在後面串接的參數中使用

# by boho

$('#dvX').width($(this).width()+20); 怎么样?也是同样的效果?

# by Phoenix

很漂亮的解法0.0 在想可不可以解決這個, result.children(".ui-datepicker-year").html(result.children(".ui-datepicker-year").html() + "年"); 改成 result.children(".ui-datepicker-year").html($._this.html() + "年");

# by Ark

效能是吧~不用花俏~更直覺的攔截 with ($(".dvx")) { width(width() +20) } with(result.children(".ui-datepicker-year")){ html(html()+"年").width(width() +20);//愛連就繼續連 height(height()+50);//愛分行就分行看 }

# by Jeffrey

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

# by pbnttttt

為了可以串接~但實不實用我不清楚@@~For Fun (function(Jobj) { with (Jobj) { width(width() + 20); } return Jobj; })($("#dvX")).text(new Date().toTimeString());

# by pbnttttt

有人提出with效能不好去查了一下~把with那段改成Jobj.width(Jobj.width() + 20);其實就跟黑暗大提出的解法2沒什麼差別吧!! 微軟提出的js效能建議,最後一點有提到避免使用with喔 http://blogs.msdn.com/ie/archive/2006/08/28/728654.aspx

# by Ark

嘿~很弱小....寫程式的龜毛人通常會出現的共同盲點 那就是.....越短越強大(和某方面需求不同) 避免使用with也是要看程式的需求 如說程式內包有大量的loop操弄某一obj,用了with可以捨去許多的"." 這時以js特性多一點 "." 就多噸一絲絲 效能就值得了,若寫成with包with或是寫成loop包到with外層 那就是老耿中的老耿嚕 其實可以觀看Jqurery1.26與1.32 1.26只出現過一次 if ( elem ) with ( jQuery.browser ) {OOXX... 到了1.32就完全消失了, 可見被大量引用的$字 對with的拔除產生的效能增加 ...可是...可是...人家喜歡短昧

# by streaker blog

人小,但大智慧

# by lucas

大推 增長見聞

# by Tony

Ark, 給你拍拍手

# by showP

各位好,小弟是上星期五才開始接觸 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;

# by Jeffrey

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

# by showP

Jeffrey 你好 再想請問一下 我寫的範例中 , 如果不加上 endAlias() , 是否會產生記憶體無法釋放的問題呢? 另外你提到的 jQuery.data 這個要怎麼用?,因為 jQuery.data 不是會一定要 binding 在一個 jQuery collection 上嗎? (http://docs.jquery.com/Core/data#namevalue) , 如果我搞混了..是否有一些範例呢? 謝謝你

# by Jeffrey

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

# by showP

Jeffrey 好 真是一語點醒夢中人啊~~ 套用你的話 (筆記,沙沙沙...) 謝謝~

# by Laurence

從黑大的 blog 認識這位在英國的少年 然後就會定期閱讀他的 blog 隔了好一陣子沒看他的文章 今天赫然發現他去年底 (2019 Dec.) 中風了 雖然保住性命了, 但現在仍在復健中 希望他能快快恢復

# by Laurence

https://j11y.io/my-life/brain-disability-revel/ 忘了附上他說明自己的近況的文章

# by Jeffrey

to Laurence,真是令人震驚的消息,James Padoley 才 30 歲耶,祝福他早日恢復。

# by Laurence

根據他個人 facebook 上的文章 是他有 AVM (一種先天性的動靜脈畸形) 導致的 https://www.facebook.com/jamespadolsey/posts/10207106192530861 真的祝福他早日恢復

Post a comment