這兩天寫程式遇到兩則jQuery議題,花了點時間才釐清,特筆記備忘。

第一個問題出現在$("#boo”).data(“foo”, fooObject).addClass(“bar”);,其於特定情況下會彈出"Error: Unable to get value of the property 'addClass': object is null or undefined"錯誤。

第二個問題,則是發現$("<div />”).attr({ att1:"boo" })$("<div />”, { att1: "…" })寫法產生不同結果。

以下是重現議題的網頁:

<!DOCTYPE html>
 
<html>
<head>
    <title>jQuery Notes</title>
    <script src="Scripts/jquery-1.6.4.js"></script>
    <script>
        $(function () {
            //TEST 1
            //測試.data()傳入null及undefined
            alert($("body").data("a", null));
            alert($("body").data("b", undefined));
 
            //TEST 2
            //建立物件並使用.attr()指定Attribute
            $("<span />").attr({ width: "120" }).appendTo("body");
            //建立物件時一併指定Attribute
            $("<span />", { width: "100" }).appendTo("body");
            alert($("body").html());
        });
    </script>
</head>
<body></body></html>

在TEST1中,$("body").data("a", null)會傳回jQuery物件,可繼續串接其他方法;但$("body").data("b", undefined)則傳回undefined,若試圖再串接其他方法便會發生錯誤。仔細一想,會發現這是Javascript語言的函數參數特性使然。例如: 當宣告function boo(a, b),呼叫時寫成boo(), boo(x), boo(x, y)皆可,原理是function中可透過typeof a == "undefined"判斷參數是否有傳入值達成忽略參數的目的。因此,$("body").data("b", undefined)便等同於$("body").data("b"),會回傳data值而非jQuery物件。

至於TEST2,其執行結果為<span width="120"></span><span style="width: 100px;"></span>。換句話說,用.attr({ width: "100"})會新增一個width Attribute,而$("<div />", { width: "100" })卻是設定style.width屬性。

追進原始碼得到解答:

attr: function( elem, name, value, pass ) {
    var nType = elem.nodeType;
    
    // don't get/set attributes on text, comment and attribute nodes
    if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
        return undefined;
    }
 
    if ( pass && name in jQuery.attrFn ) {
        return jQuery( elem )[ name ]( value );
    }

當透過$("<div />", { width: "100" })呼叫attr()時,pass == true,而"width"是jQuery.attrFn表列函數之一,實際上會執行.width("100")。但追完原始碼才驚覺自已的老毛病又犯了,不先查文件就一味鑽Code,其實,jQuery的官方文件早已揭示,第二個傳入的參數不只對應.attr(),還包含事件、html()、val()、width()... 等(而以前我一直以為它只用來設定.attr()):

As of jQuery 1.4, the second argument to jQuery() can accept a map consisting of a superset of the properties that can be passed to the .attr() method. Furthermore, any event type can be passed in, and the following jQuery methods can be called: val, css, html, text,data, width, height, or offset. The name "class" must be quoted in the map since it is a JavaScript reserved word, and "className" cannot be used since it is not the correct attribute name.

提醒自己,下回要多點耐性RTFM,別成天想著UTSL~~


Comments

Be the first to post a comment

Post a comment