為了歡度jQuery四歲生日(jQuery由John Resig 於 2006/01/14 在 BarCamp NYC 首次發表[註]),jQuery開發團隊在2010/01/14釋出了jQuery 1.4版

簡單整理一下我所理解的1.4改版重點:

  1. 大量重構常用的函數,降低程式複雜度(主要是減少內部函數彼此呼叫的次數),達到改善效能的目標。
  2. *.css(), .attr(), .val(), .html(), .text(), .append(), .prepend(), .before(), .after(), .replaceWith(), .wrap(), .wrapInner(), .offset(), .addClass(), .removeClass(), .toggleClass() 可傳入函數,由函數的傳回值當作參數值。(傳入函數當成參數的做法,有個術語叫Function Settter)
  3. *.css(), .attr(), .val(), .html(), .text(), .append(), .prepend(), .offset(), .addClass(), .removeClass(), .toggleClass() 在Function Setter時,該函數的第二個參數即原值。這點很方便,例如,如果要在所有的<a>顯示文字的後方加上"[L]"字串,過去會寫成:
    $("a”).each(function(i) { var $a = $(this); $a.html($a.html() + "[L]"); });
    現在可以結合2, 3點的新功能,寫成:
    $("a”).html(function(i, html) { return html + “[L]”; });
    變簡單很多吧!
  4. $.ajax在傳送陣列參數時,預設會改用ary[]=elem1&ary[]=elem2的Query String表示法(過去會轉成ary=elem1&ary=elem2),這多半跟PHP、Ruby on Rails搭配使用。 如果想要保留原做法,需另外設定jQuery.ajaxSettings.traditional = true;
  5. *$.ajax可不指定dataType,由Response的ContentType決定: applcation/json時自動調為"json",text/javascript或application/x=javascript時變成”script”,text/xml時視為"xml”。
  6. $.ajax設定ifModified:true時,支援ETag檢查決定是否使用Cache的內容。
  7. *JSON解析原本都是用eval,從1.4起會在Browser有支援的情況下使用內建的JSON Parser(如: IE8, FF3.1, Chrome, Safari),比eval來得安全也更有效率。
  8. .serialize支援HTML5的欄位元素,例如: datetime, range。
  9. *$.ajax多了context參數,在Callback函數中可以透過this直接存取context所傳入的元素物件,不必再用Closure,簡單很多! 例如:
    $.ajax({
        url: “gettime.aspx”,
        context: $(“#spnNowTime”),
        success: function(s) { context.html(s); }
    });
  10. $.get, $.post, $getJSON, $.getScript 的success Callback多了第三個傳入參數--XHR。以前若想存取XHR,就必須放棄$.get等簡易寫法,回頭改用$.ajax。
  11. 送出AJAX Request時不管有無資料內容,一律傳送Content-Type Header,以符合某些應用場合的要求。
  12. 可以指定JSONP的callback函數名稱了! 也就是在邊做邊學jQuery第14集中提到的jsonp1238089172708,現在可透過jsonpCallback參數自訂。
  13. $.ajax用onreadystatechange取代setTimeout輪詢,改善效能 。
  14. .text()支援CDATA
  15. *很酷的新HTML元素建構寫法:
    jQuery("<div/>", {
        id: "foo",
        css: {
            height: "50px",
            width: "50px",
            color: "blue",
            backgroundColor: "#ccc"
        },
        click: function() {
           $(this).css("backgroundColor", "red");
        }
    }).appendTo("body");
  16. *.eq(-N), .get(-N)可以取"倒數第N個",.first(), .last()可以取第一個跟最後一個。
  17. 過去jQuery()會傳回document的jQuery物件,1.4版起則改為傳回空的jQuery集合,以便動態加入元素。jQuery().ready()在1.4仍維持jQuery(document).ready()的效果,但建議不要再用了。
  18. jQuery(“tagName”)改用getElementByTagName,速度大幅改善;$("<div>”), $(“<div />”), $(“<div></div>”)均改用document.createElement,$(“<div></div>”)效能己改善。
  19. .css()加快兩倍、.addClass(), removeClass(), .hasClass()加快三倍。
  20. .toggleClass()支援一次切換多個class,例如: toggleClass("class1 class2")。
  21. *.data(myCacheObject)可以用傳入的物件置換掉整個Cache物件,而.data()可以取回整個Cache物件。
  22. .data()使用的Cache物件改成有用到才建立,以改善效能。
  23. 呈現動畫時,可針對不同屬性設定不同的Easing效果。[參考: 天才少年James PadolseyDemo]
  24. jQuery.proxy()可以為現有函數產生一個分身,並指定該分身的Scope(簡單來就是強制指定this)。這有什麼用呢? 常見的案例是在事件函數中,要用另一個元素當作this。例如:
    var f = function() { alert(this.id); };
    $("#A,#B").click(jQuery.proxy(f, $("#A")[0]));

    在A,B上掛了同一個click事件,但透過jQuery.proxy指定Scope為A,則B的click事件裡,this也會指向A。
  25. .bind()時可傳入物件{ click: function() { … }, keydown: function() { … } },一次指定多個事件。
  26. *克服了change(), submit()在IE裡跟其他瀏覽器部分行為有差異的問題。
  27. *新事件focusin, focusout。類似focus及blur,但是支援Bubble Up。應用範例,<p>中包了<input>,當<input>取得焦點時,<p>的focusin事件也會被觸發。
  28. *除了ready, focus(可用focusin取代), blur(可用focusout取代),所有的事件都可以.live()了,萬歲!!! 另外,live的對象也可以指定Context了。(這應該可以克服上回在滲透式live管不到Iframe document的問題)
  29. .ready()會使用setTimeout持續檢查document.body是否存在,原則上只用來解決Safari瀏覽器的少數問題案例。
  30. 非IE瀏覽器不再做unload事件的Memory Leak檢查以加快速度。
  31. .append(), .prepend(), .before(), .after()變快約一倍,.html()變快三倍,.remove(), .empty()變快4倍。
  32. 新方法: .detach(),將元素自DOM移除,但保留事件函數,多半用在暫時移除,稍後加回去的情境。
  33. 新方法: .unwrap(),剝掉外層,留下html()的部分。例如: <div id="X"><span>A</span></div>,$("#X").unwrap() -> <span>A</span>
  34. 內部函數domManip加入Cache機制,jQuery("<div>"), .after("<div>")會比以前快。
  35. 沒有加進DOM的物件也可以用.before(), .after(), .replaceWith()。例如: jQuery("<div/>").before("<p>Hello</p>").appendTo("body") 。
  36. *.clone(true)現在連.data()也一併會複製 。
  37. .offset()支援設定功能,可用來改變元素位置。(設定時,CSS position會被自動改成relative)
  38. *queue()不再只侷限在動畫應用上,新增.delay(n)函數,可暫停n ms、.next()可跳到下一個動作、clearQueue()可以清除動作。
  39. *.index()取得元素在同層元素中的排行,.index(selector)取得元素在同層元素同符合selector的排行。
  40. .has()。$("div”).has(“a”) 相當於 $("div:has(a)”)
  41. .nextUntil(), .prevUntil(), parentsUntil(),類似.nextAll(), .prevAll(), .parents(),但會一直向後/前/上蒐集元素,直到符合selector元素為止。
  42. .add(), .closest()支援傳入第二個參數作為Context 。
  43. jQuery.isEmptyObject()用來判別是否物件沒有任何屬性 。
  44. jQuery.isPlainObject()用來判別是否為物件 。
  45. jQuery.contains(A, B)用來判別元素B是否被包在元素A中 。
  46. *jQuery.noop(),什麼事都不做的空函數,用在一定要傳入函數作為參數的場合。
  47. jQuery.unique(),只保留DOM元素陣列中不重複的部分,並依在DOM出現順序排列。
  48. 其他: jQuery.browser支援Engine導向,例如: jQuery.browser.webkit用來判別所有以WebKit開發的Browser、對Java Applet的支援更好、不再使用arguments.callee(ECMAScript 5要廢掉)、使用Closure Compiler而非YUI Min來壓縮jquery-1.4.min.js 。

【改版後不相容之處】

改用1.4,請注意以下的寫法可能會出問題:

  1. .add()的結果改成依元素在DOM裡的順序排列
  2. .clone(true)會一併複製事件跟.data()儲存的資料
  3. jQuery.data(elem)不再只傳回id字串,而是該元素的.data() Cache物件
  4. jQuery() != jQuery(document)
  5. *.val(“…”)作用在<option>或<input type=”checkbox”>時,只認value,不再看text
  6. *jQuery.browser.version現在傳回Engine版本
  7. 將會阻擋格式不符規定的JSON表示字串
  8. *預設會以PHP/Rails的ary[]=elem1&ary[]=elem2方法序列化參數,如想維持ary=elem1&ary=elem2的做法,請設定jQuery.ajaxSettings.traditional = true;
  9. 內建屬性jQuery.className移除
  10. jQuery.extend(true, …)將不再適用於非物件及陣列
  11. *$.ajax未指定dataType,而Response.ContentType == “text/javascript”時,將會自動被當成Script執行,不再當成string處理
  12. $.ajax的ifModified會一併納入ETags決定是否使用Cache。

好消息是,如果你發現原來的js換了1.4有以上問題,懶得改程式又很想用1.4,只要加掛一個Plug-In就可以解決。
<script src="/img/loading.svg" data-src="http://code.jquery.com/jquery.js"></script>
<script src="/img/loading.svg" data-src="http://code.jquery.com/jquery.compat-1.3.js"></script>

我只能說,jQuery真是佛心來著呀!!

【註】紅色*是我個人認為值得關注的改變


Comments

# by 路人甲

大大您好 不知您的邊做邊學jquery系列裡的示範是如何達成 就是不用在program model那打程式碼 直接在htm的執行頁面打jquery語法就會直接執行

# by Bonnie

你好: 我這裡遇到一個現象,是使用IE7/8才會發生的,IE6、Firefox 3.5及Chrome 3沒問題。 我在 html 中外部載入一份 a.js,並且於 a.js 中呼叫 $.getScript("b.js"),然後執行 b.js 中的函式。 而這個函式僅簡單 alert("Hello!") 我用IE7/8測試時,「第一次」載入網頁,會跳出「Permission Dynied」的訊息,重新整理後又可以正常顯示「Hello!」 而trace後,發現是卡在 jquery-1.4.js 產生 XMLHTTPRequest 的地方,和1.3.2比對後,發現這版改寫了判斷的方式,我有先咕狗過,這版的寫法看來是比較有彈性也較正確的方式,不過,不知道為何會在IE7/8上出問題。 不知道你是否遇過?該怎麼解呢? 謝謝~

# by Bonnie

你好: 我這裡遇到一個現象,是使用IE7/8才會發生的,IE6、Firefox 3.5及Chrome 3沒問題。 我在 html 中外部載入一份 a.js,並且於 a.js 中呼叫 $.getScript("b.js"),然後執行 b.js 中的函式。 而這個函式僅簡單 alert("Hello!") 我用IE7/8測試時,「第一次」載入網頁,會跳出「Permission Dynied」的訊息,重新整理後又可以正常顯示「Hello!」 而trace後,發現是卡在 jquery-1.4.js 產生 XMLHTTPRequest 的地方,和1.3.2比對後,發現這版改寫了判斷的方式,我有先咕狗過,這版的寫法看來是比較有彈性也較正確的方式,不過,不知道為何會在IE7/8上出問題。 不知道你是否遇過?該怎麼解呢? 謝謝~

# by Bonnie

阿 抱歉 送了兩次 麻煩請直接刪除重複的部份 3Q

# by Ark

a.js中$.getScript("b.js") 是否放在 $(function(){...});內 如果是在ready 就想執行~須注意

# by Bonnie

to Ark, 確實是放在$(function(){...});內 但我不太了解其中的原理,可否說明一下呢?

# by 路人甲

感謝Jeffrey大大 這東西超方便 不用在一直編譯就可測試打的JavaScript對不對 小弟我也想變JavaScript神手!!!

# by Ark

to Bonnie 我猜測的原因是IE有安全性原則的套用問題 啥信任網站的 第2次成功可能是抓快取的

# by Mesak

各位好,最近在寫 一些 greasemonkey 的程式 檔程式越寫越大之後,發現效能越托越慢 我能想到的有幾個問題 1. 物件 重複呼叫 2. 屬性 存取data 是否會影響效能 3. 事件的綁定 請問 還有沒有方法可以增加 jquery 的效能呢??

# by Jeffrey

to Mesak, 依我的經驗,要調效能要先抓出瓶頸,有時瓶頸改兩行的效果遠勝過依據某些效能原則全面改寫程式(當然,平日寫Code就依循效能原則,絕對是正確的,你可以用"jquery performance tips"關鍵找到不少探討文章)。建議可以善用一些工具(如: IE8 Dev Tools, http://bit.ly/ahyzDL)看看程式慢在哪裡,會比應用一般性原則去改寫程式更能有效改善速度,若GreaseMonkey的程式偵錯或監測不易,可設法拉出成一般js驗證後再搬回去。

# by Mesak

謝謝 Jeffrey 的回答跟資料,請問一下 firefox 有類似的 addons 可以監控函式的呼叫次數等 紀錄可用嗎? 因為我是寫 遊戲的腳本,所以 模擬相同的 環境不太容易,所以還是得用 FIREFOX 測試 除錯....

# by Mesak

我開啟主控台,json 會被插入 firebug的資訊.....

Post a comment