国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JS魔法堂:那些困擾你的DOM集合類型

468122151 / 2041人閱讀

摘要:五的子類對象會返回一個集合對象,集合內存儲類型的元素。七的子類初看很有可能以為集合元素就是單選表單元素,其實可以存儲任意類型的表單元素。八的子類開始,將返回子類的對象,其行為特征和一致。但在前,我們應該先了解清楚的類型的特征。

一、前言                           

大家先看看下面的js,猜猜結果會怎樣吧!

可選答案:

①. 獲取id屬性值為id的節點元素

②. 拋namedItem is undefined的異常

var nodes = document.getElementsByName("dummyName");
var node = nodes.namedItem("id");

  答案是兩種都有可能哦!document.getElementsByName在Chrome和FF30.0中返回NodeList(木有namedItem方法的),在IE全系列中都返回HTMLCollection,吐血了吧?

  DOM集合又何止這些呢,下面我們就一起來探討一下吧!

二、困擾你我的NodeList與HTMLCollection

相同點:

1. 類數組。有length屬性,可以用下標索引來訪問其中的元素,但沒有Array的slice等方法;

2. 只讀。無法增刪其中的元素;

3. 實時同步DOM樹的變化。若DOM樹有新元素加入,該類型的對象也會將新元素包含進來;

4. 可通過下標數字類型索引獲取集合中指定位置的元素;

5. 可通過item({String | Number} 索引)方法獲取集合中指定位置的元素,若通過索引找不到元素,則以第一個元素作為返回值。

不同點(主要表現在HTMLCollection比NodeList能力更強大):

1. HTMLCollection對象可通過namedItem({String} id或name)獲取首個匹配的元素,若沒有則返回null;

2. HTMLCollection對象可通過點方式獲取第個id或name匹配的元素,若沒有則返回undefined。

各瀏覽器選擇器返回類型差別:

// IE678 返回具有HTMLCollection特征(有namedItem方法)的[object Object]對象
// IE9、10、11、FF、Chrome均返回HTMLCollection
document.images;
document.links;
document.anchors;
document.forms;
document.embeds;
document.scripts;
document.applets;
document.plugins;
Node對象.getElementsByTagName;
Node對象.getElementsByTagNameNS;
Node對象.getElementsByClassName;
HTMLTableElement對象.tBodies;
HTMLTableElement對象.children;
HTMLTableElement對象.rows;
HTMLTableRowElement對象.cells;
HTMLMapElement對象.areas;


// IE678 返回具有HTMLCollection特征(有namedItem方法)的[object Object]對象
// IE9、10、11返回HTMLCollection
// FF30.0、Chrome返回NodeList
document.getElementsByName;

// IE678 返回具有NodeList特征(無namedItem方法)的[object Object]對象
// IE9、10、11、FF、Chrome均返回NodeList
Node對象.childNodes;

// IE5678 返回具有HTMLCollection特征(有namedItem方法)的[object Object]對象
// IE9、10返回[object HTMLCollection]
// IE11、Chrome返回[object HTMLAllCollection]
// FF30.0返回[object HTML document.all class]
document.all;

總體來說Chrome的實現更接近W3C規范;

HTMLAllCollection、HTMLCollection和[object HTML document.all class]功能沒什么區別,只是類型不同而已;

由于document.getElementsByName在不同的瀏覽器中返回不同類型的對象,因此推薦使用[{Number} 索引]的方法來訪問集合元素會省心一些;

題外話:children屬性僅獲取nodeType為1的元素,而childNodes會將所有子元素的包含進來;

注意:IE9、10、11的HTMLCollection與其他瀏覽器的HTMLCollection可不相同哦,具體請看下一節吧!

三、同名不同性——IE下怪異的HTMLCollection 

  假如大家看過《JS魔法堂:追憶那些原始的選擇器》,應該會了解到在IE5678下,document.all會返回一個類函數對象,也就是上文說到的帶有HTMLCollection特征的[object Object]對象。其實IE這一傳統一直延續到IE11,這就導致IE9、10、11下的HTMLCollection與W3C標準出現同名而不同性質的問題了。

  何為類函數?

純屬本人私自定義而已,用于指那些擁有函數的特征,但instanceof Function卻返回false的對象。

真心想對IE說一句,你這么吊,你媽媽知道嗎?

四、StaticNodeList——偽裝成NodeList的小子          

  從IE8開始就多了個querySelectorAll選擇器方法。具體行為如下:

// IE8返回 [object Object], IE9+和chrome、FF就返回[object NodeList]
var nodes =  document.querySelectorAll("*");

// IE8返回 空集合[object Object],IE9+和chrome、FF就拋至少是1個函數入參的異常
nodes = document.querySelectorAll();

// 各瀏覽器均拋SyntaxError異常
nodes = document.querySelectorAll("") 或 document.querySelectorAll(非字符串類型入參);

大家不要被瀏覽器返回的NodeList所蒙騙,其實querySelectorAll返回的是StaticNodeList對象。其特征與NodeList基本無異,唯一的區別就是StaticNodeList是不會實時同步DOM樹變化,因此在polyfill querySelectorAll的時候就不用考慮實時同步DOM樹變化的問題了。

五、HTMLOptionsCollection——HTMLCollection的子類     

  HTMLSelectElement對象.options會返回一個HTMLOptionsCollection集合對象,集合內存儲HTMLOptionElement類型的元素。HTMLOptionsCollection類型除了父類HTMLCollection的特征外,還有如下成員方法、屬性可用。

add({HTMLOptionElement} opt[, {HTMLOption | Number} before]); // 將選項元素加入到集合的最后,或指定的元素(位置)的后面
remove({Number} index);// 刪除指定位置的選項
selectedIndex; // 當前選中項的索引,從0開始

六、HTMLFormControllersCollection——HTMLCollection的子類

  HTMLFormElement對象.elements會返回一個HTMLFormControllersCollection集合對象,集合內存儲各種表單元素。它特別之處是通過點屬性獲取id或name匹配的元素時,一般的HTMLCollection集合對象在即使有多個匹配的元素的情況下,僅返回首個匹配的元素;而HTMLFormControllersCollection,在有一個匹配的元素時就返回該元素,若有多個匹配的元素則返回一個RadioNodeList集合對象。

              

七、RadioNodeList——NodeList的子類

  初看RadioNodeList很有可能以為集合元素就是單選表單元素,其實RadioNodeList可以存儲任意類型的表單元素。不過其value屬性就值顯示其中被選中的單選項表單元素的value值,若沒有單選項表單元素,或沒有選中單選項表單元素,那么value值為空字符串。

八、HTMLAllCollection——HTMLCollection的子類        

  IE11、Chrome開始,document.all將返回HTMLCollection子類HTMLAllCollection的對象,其行為特征和HTMLCollection一致。但IE11中的HTMLAllCollection還可以當作函數使用,具體請看本文的第三節。

九、NamedNodeMap——無序Attr元素集合    

  HTMLElement對象.attributes會返回NamedNodeMap集合對象,內部保存的是[object Attr]類型的對象。NamedNodeMap和HTMLCollection、NodeList不同,因為它是無序集合,雖然可以通過數字類型的下標索引訪問NamedNodeMap集合中的元素,但該索引值并不真實代表元素在集合中的位置。下面是NamedNodeMap的成員方法:

[{String} 屬性名]
item({Number | String} 索引)
getNamedItem(); //通過名稱返回指定的屬性節點
getNamedItemNS(); //通過名稱和命名空間返回指定的屬性節點
setNamedItem(); //通過名稱設置指定的屬性節點
setNamedItemNS(); //通過名稱和命名空間設置指定的屬性節點
removeNamedItem(); //通過名稱刪除指定的屬性節點
removeNamedItemNS(); //通過名稱和命名空間刪除指定的屬性節點

注意:HTMLElement對象.attributes僅返回顯示屬性(簡單地說就是直接寫在html標簽上的屬性,或通過setAttribute設置的屬性,具體請看《JS魔法堂:不要再被Attribute和Property困擾我們了》)

十、DOMTokenList——HTML5新特性classList的類型哦!   

  用過classList的都知道它大大提高了我們設置css類的效率,但IE10以下卻不支持,polyfill可以幫我們一把。但在polyfill前,我們應該先了解清楚classList的類型DOMTokenList的特征。

  1. 只讀

  2. 實時同步相應元素的className屬性值的變化

  3. 擁有以下方法和屬性

 {Undefined} add({String} class); // 已存在的類不會被重復添加
 {Undefined}  remove({String} class)
 {Undefined}  toggle({String} class)
 {Boolean} contains({String} class); //檢查是否有指定的類
 item({Number} 索引); //通過索引獲取指定位置的類
 length; //表示類的個數
 // 無法通過[{Number} 索引]的方式來設置類,只能通過該方式來獲取類

  那么現在我們就著手polyfill吧,注意難點在實時同步這一塊,解決辦法就是用onpropertychange來監聽className的變化(想了解更多,請看《JS魔法堂:DOM世界的觀察者》)

function polyfillClassList(el){
  var r = /s+/, cls = el.className, _inner  =  cls ? cls.trim().split(r) : [];
  var listener = function(e){
    if (e.propertyName !== "className") return void 0;

    var cLst = el.classList, oLen = _inner.length, cls=  el.className;
    _inner  =  cls ? cls.trim().split(r) : [];
    var len = (cLst.length = _inner.length);
    for (var i = 0, maxLen = Math.max(oLen, len); i < maxLen; ++i){
       if (i < len){
           cLst[i] = _inner[i])
       } else {
           delete cLst[i];
       }
    }    
  };
  el.attachEvent("onpropertychange", listener);
  el.classList = {
     length: _inner.length,
     item: function(index){
        return _inner[index] || null;
     },
     add: function(cls){
       // 省略檢查cls值是否有效的代碼
       if (this.contains(cls)) return void 0;

       el.detachEvent("onpropertychange",  listener);
       el.className += " " + cls;
       _inner.push(cls);
       this[this.length++] = cls;
       el.attachEvent("onpropertychage", listener);
     },
     remove: function(cls){
       // 省略檢查cls值是否有效的代碼
       if (!this.contains(cls)) return void 0;

       el.detachEvent("onpropertychange",  listener);
       el.className = el.className.replace(new RegExp("" + cls + "", "i"), "").trim();
       _inner.splice(_inner.indexOf(cls), 1);
       --this.length;
       el.attachEvent("onpropertychage", listener);
     },
     toggle: function(cls){
       // 省略檢查cls值是否有效的代碼
       this[this.contains(cls) ? "remove" : "add"](cls);
     },
     contains: function(cls){
       // 省略檢查cls值是否有效的代碼
       return el.className.search(new RegExp("" + cls + "", "i")) >= 0;
     },
     toString: function(){
       return _inner.toString();
     }
  };  

  // 初始化classList[{Number} 索引]獲取Attr元素
  for (var i = 0, len = _inner.length; i < len; ++i ){
    el.classList[i] = _inner[i];
  }
}        

由于當原生的add、remove、contains和toggle方法的入參值包含空格時,會拋出InvalidCharacterError,因此在polyfill時也要做相應的檢查和拋出異常

// 模擬InvalidCharacterError類
var InvalidCharacterError =  function(msg){
   this.code = 5;
   this.message = msg;
   this.name = "InvalidCharacterError";
};
InvalidCharacterError.prototype = DOMException;


// 檢查入參并拋異常
// @param {String} methodName add、remove等方法名
// @param {String} cls css類
var check = function(methodName, cls){
  var msgTpl = ["Failed to execute "", , "" on "DOMTokenList": The token provided ("", ,"") contains HTML space characters, which are not valid in tokens."];
  if (/s+/.test(cls)){
     throw new InvalidCharacterError((msgTpl[1] = methodName, msgTpl[3] = cls, msgTpl).join(""));
  }
};

更多關于異常處理、Error和Exception的信息請留意《JS魔法堂:異常處理并不那么簡單》

十一、DOMStringMap類型——HTML5新特性dataset的類型哦!  

  IE11開始支持 HTML5 JS API的dataset,它是就專門用來操作自定義特性(custom attribute,屬性的分類請看《JS魔法堂:特性、屬性,傻傻分不清楚》)的對象,其類型為DOMStringMap,從名稱可知其為字符串字典。下面結合dataset說明其特點吧,具體如下:

  ①. dataset針對以"data-"開頭的自定義特性操作;

  ②. 通過形如dataset.rawData獲取data-raw-data的屬性值;

  ③. 通過形如dataset.rawData = "hello world!"給data-raw-data的屬性賦值;

  ④. 通過形如delete dataset.rawData刪除屬性data-raw-data;

  ⑤. 通過for in 遍歷dataset的屬性;

  ⑥. 屬性值必須或將自動轉換為String類型;

  ⑦. 其實它就是除了setAttribute、getAttribute等操作自定義特性的另一個接口而已,而且效率比get/setAttribute低,但大大簡化操作代碼。

  另外,JQuery中也有一個data函數,那么它跟以"data-"開頭的自定義特性有什么關聯呢?

html:

,使用jquery-1.10.2

        var $el = $("#div"), el = $el[0]; 

        function log(){
            console.log($el.data("raw"));
            console.log(el.dataset["raw"]);
            console.log(el.outerHTML);
        }
        log();
     // 輸出:
     // raw
     // raw
        // 

$el.data("raw", "$"); log(); $el.data("raw", "raw");      // 輸出:      // $      // raw      //
el.dataset.raw = "dataset"; log(); el.dataset.raw = "raw";      // 輸出:      // raw      // dataset      //
delete el.dataset.raw; log(); // 輸出: // raw // undefined //
el.dataset.newRaw = "newRaw"; console.log($el.data("newRaw")); // 輸出newRaw

  從上面的實例可知:

    調用JQuery的data函數訪問屬性時,它會在庫內部的特性映射表中尋找同屬性名的鍵值對,沒有則采取與dataset相同的方式獲取屬性值,若成功則將在特性映射表中新建一個鍵值對,然后后續的訪問和賦值操作均僅僅針對該鍵值對。賦值操作時,僅僅在特性映射表中新建鍵值對,并不會賦值到標簽對應的"data-*"特性中。

    為何JQuery要設計成這樣呢?因為dataset的自定義特性值必須為String類型,賦予其他類型時會發生隱式類型轉換,不便于暫存對象、數組等數據。JQuery這種算是折中的做法吧,所以用JQuery的data API操作自定義特性時最好不要跟dataset或get/setAttribute等原生API混合用咯。

  本節參考:《HTML5自定義屬性對象Dataset 簡介》

十二、 總結                        

其實DOM的集合又何止上述的這些呢,在后續的日子里我會邊學習邊完善本文的,謝謝收看!

如果您覺得本文的內容有趣就掃一下吧!捐贈互勉!

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/85860.html

相關文章

  • JS魔法之實戰:純前端的圖片預覽

    摘要:一前言圖片上傳是一個普通不過的功能,而圖片預覽就是就是上傳功能中必不可少的子功能了。偶然從上找到純前端圖片預覽的相關資料,經過整理后記錄下來以便日后查閱。類型為,表示在讀取文件時發生的錯誤,只讀。 一、前言   圖片上傳是一個普通不過的功能,而圖片預覽就是就是上傳功能中必不可少的子功能了。在這之前,我曾經通過訂閱input[type=file]元素的onchange事件,一旦更改路徑...

    岳光 評論0 收藏0
  • 前端魔法:解秘FOUC

    摘要:前言對于問題多多的,瀏覽器樣式閃爍是一個不可忽視的話題,但對于的瀏覽器就不用理會了嗎下面嘗試較全面地解密。示例說明,不管在哪里引入,在頁面的所有下載完成前,整個頁面將不會被渲染。 前言 ?對于問題多多的IE678,FOUC(flash of unstyled content)——瀏覽器樣式閃爍是一個不可忽視的話題,但對于ever green的瀏覽器就不用理會了嗎?下面嘗試較全面地解密F...

    Dean 評論0 收藏0
  • 前端魔法:解秘FOUC

    摘要:前言對于問題多多的,瀏覽器樣式閃爍是一個不可忽視的話題,但對于的瀏覽器就不用理會了嗎下面嘗試較全面地解密。示例說明,不管在哪里引入,在頁面的所有下載完成前,整個頁面將不會被渲染。 前言 ?對于問題多多的IE678,FOUC(flash of unstyled content)——瀏覽器樣式閃爍是一個不可忽視的話題,但對于ever green的瀏覽器就不用理會了嗎?下面嘗試較全面地解密F...

    MRZYD 評論0 收藏0
  • 前端魔法:解秘FOUC

    摘要:前言對于問題多多的,瀏覽器樣式閃爍是一個不可忽視的話題,但對于的瀏覽器就不用理會了嗎下面嘗試較全面地解密。示例說明,不管在哪里引入,在頁面的所有下載完成前,整個頁面將不會被渲染。 前言 ?對于問題多多的IE678,FOUC(flash of unstyled content)——瀏覽器樣式閃爍是一個不可忽視的話題,但對于ever green的瀏覽器就不用理會了嗎?下面嘗試較全面地解密F...

    VEIGHTZ 評論0 收藏0
  • CSS魔法:一起玩透偽元素和Content屬性

    摘要:前言繼上篇魔法堂稍稍深入偽類選擇器記錄完偽類后,我自然而然要向偽元素伸出魔掌的啦。和的注意事項默認必須設置屬性,否則一切都是無用功默認,就是和的內容無法被用戶選中的偽元素和偽類結合使用形如。 前言 ?繼上篇《CSS魔法堂:稍稍深入偽類選擇器》記錄完偽類后,我自然而然要向偽元素伸出魔掌的啦^_^。本文講講述偽元素以及功能強大的Contet屬性,讓我們可以通過偽元素更好地實現更多的可能! ...

    DevTalking 評論0 收藏0

發表評論

0條評論

468122151

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<