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

資訊專(zhuān)欄INFORMATION COLUMN

【underscore.js 源碼解讀】for ... in 存在的瀏覽器兼容問(wèn)題你造嗎

Pikachu / 766人閱讀

摘要:最近開(kāi)始看源碼,并將源碼解讀放在了我的計(jì)劃中。像和使用內(nèi)置構(gòu)造函數(shù)所創(chuàng)建的對(duì)象都會(huì)繼承自和的不可枚舉屬性,例如的方法或者的方法。循環(huán)將迭代對(duì)象的所有可枚舉屬性和從它的構(gòu)造函數(shù)的繼承而來(lái)的包括被覆蓋的內(nèi)建屬性。

Why underscore

最近開(kāi)始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計(jì)劃中。

閱讀一些著名框架類(lèi)庫(kù)的源碼,就好像和一個(gè)個(gè)大師對(duì)話(huà),你會(huì)學(xué)到很多。為什么是 underscore?最主要的原因是 underscore 簡(jiǎn)短精悍(約 1.5k 行),封裝了 100 多個(gè)有用的方法,耦合度低,非常適合逐個(gè)方法閱讀,適合樓主這樣的 JavaScript 初學(xué)者。從中,你不僅可以學(xué)到用 void 0 代替 undefined 避免 undefined 被重寫(xiě)等一些小技巧 ,也可以學(xué)到變量類(lèi)型判斷、函數(shù)節(jié)流&函數(shù)去抖等常用的方法,還可以學(xué)到很多瀏覽器兼容的 hack,更可以學(xué)到作者的整體設(shè)計(jì)思路以及 API 設(shè)計(jì)的原理(向后兼容)。

之后樓主會(huì)寫(xiě)一系列的文章跟大家分享在源碼閱讀中學(xué)習(xí)到的知識(shí)。

underscore-1.8.3 源碼全文注釋 https://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/underscore-1.8.3-analysis.js

underscore-1.8.3 源碼解讀項(xiàng)目地址 https://github.com/hanzichi/underscore-analysis

underscore-1.8.3 源碼解讀系列文章 https://github.com/hanzichi/underscore-analysis/issues

歡迎圍觀~ (如果有興趣,歡迎 star & watch~)您的關(guān)注是樓主繼續(xù)寫(xiě)作的動(dòng)力

for ... in

今天要跟大家聊聊 for ... in 在瀏覽器中的兼容問(wèn)題。

for ... in 大家應(yīng)該都不陌生,循環(huán)只遍歷可枚舉屬性。像 Array 和 Object 使用內(nèi)置構(gòu)造函數(shù)所創(chuàng)建的對(duì)象都會(huì)繼承自 Object.prototype 和 String.prototype 的不可枚舉屬性,例如 String 的 indexOf() 方法或者 Object 的 toString 方法。循環(huán)將迭代對(duì)象的所有可枚舉屬性和從它的構(gòu)造函數(shù)的 prototype 繼承而來(lái)的(包括被覆蓋的內(nèi)建屬性)。

我們舉個(gè)簡(jiǎn)單的例子:

var obj = {name: "hanzichi", age: 30};

for (var k in obj) {
  console.log(k, obj[k]);
}

// 輸出
// name hanzichi
// age 30

等等,你跟我說(shuō) for ... in 這玩意有瀏覽器兼容性?!從來(lái)沒(méi)注意過(guò)啊,好像工作中也沒(méi)碰到過(guò)這樣的兼容性問(wèn)題啊!確實(shí)如此,for ... in 要出問(wèn)題,得滿(mǎn)足兩個(gè)條件,其一是在 IE < 9 瀏覽器中(又是萬(wàn)惡的 IE!!),其二是被枚舉的對(duì)象重寫(xiě)了某些鍵,比如 toString。

還是舉個(gè)簡(jiǎn)單的例子:

var obj = {toString: "hanzichi"};

for (var k in obj) {
  alert(k);
}

ok,在 chrome 中我們 alert 出了預(yù)期的 "toString",而在 IE 8 中啥都沒(méi)有彈出。

我們回頭看看 for ... in 的作用,循環(huán)遍歷 可枚舉屬性,那么顯然 IE 8 將 toString "內(nèi)定" 成了不可枚舉屬性(盡管已經(jīng)被重寫(xiě))。那么如何判斷是否在類(lèi)似 IE 8 這樣的環(huán)境中呢?underscore 中有個(gè) hasEnumBug 函數(shù)就是用來(lái)做這個(gè)判斷的:

// Keys in IE < 9 that won"t be iterated by `for key in ...` and thus missed.
// IE < 9 下 不能用 for key in ... 來(lái)枚舉對(duì)象的某些 key
// 比如重寫(xiě)了對(duì)象的 `toString` 方法,這個(gè) key 值就不能在 IE < 9 下用 for in 枚舉到
// IE < 9,{toString: null}.propertyIsEnumerable("toString") 返回 false
// IE < 9,重寫(xiě)的 `toString` 屬性被認(rèn)為不可枚舉
var hasEnumBug = !{toString: null}.propertyIsEnumerable("toString");

代碼一目了然,用了 propertyIsEnumerable 方法。

那么哪些屬性被重寫(xiě)之后不能用 for ... in 在 IE < 9 下枚舉到呢?有如下這些:

// IE < 9 下不能用 for in 來(lái)枚舉的 key 值集合
var nonEnumerableProps = ["valueOf", "isPrototypeOf", "toString",
                    "propertyIsEnumerable", "hasOwnProperty", "toLocaleString"];

恩,應(yīng)該還漏了個(gè) constructor。

我們來(lái)看看 underscore 是怎么做的。

function collectNonEnumProps(obj, keys) {
  var nonEnumIdx = nonEnumerableProps.length;
  var constructor = obj.constructor;

  // proto 是否是繼承的 prototype
  var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;

  // Constructor is a special case.
  // `constructor` 屬性需要特殊處理
  // 如果 obj 有 `constructor` 這個(gè) key
  // 并且該 key 沒(méi)有在 keys 數(shù)組中
  // 存入數(shù)組
  var prop = "constructor";
  if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
  
  // nonEnumerableProps 數(shù)組中的 keys
  while (nonEnumIdx--) {
    prop = nonEnumerableProps[nonEnumIdx];
    // prop in obj 應(yīng)該肯定返回 true 吧?是否不必要?
    // obj[prop] !== proto[prop] 判斷該 key 是否來(lái)自于原型鏈
    if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
      keys.push(prop);
    }
  }
}

proto 變量保存了原型,一個(gè)對(duì)象的原型可以通過(guò) obj.constructor.prototype 獲取,但是如果重寫(xiě)了 constructor 很顯然就無(wú)法這樣獲取了,則用 Object.prototype 替換。這樣比如說(shuō)重寫(xiě)了 toString,我們只需要比較 obj.toString 是否和 proto.toString 引用相同即可。個(gè)人覺(jué)得源碼中的 prop in obj 判斷多余了,這不肯定返回 true 嗎?如果有理解錯(cuò)誤,望指出。

而對(duì)于重寫(xiě)了 constructor 的情況,underscore 用 hasOwnProperty 進(jìn)行判斷。

對(duì)于重寫(xiě)了以上幾種屬性的情況,underscore 確實(shí)能夠獲取其在 IE < 9 中的鍵,但是愛(ài)鉆牛角尖的樓主也十分不解,constructor 真的有必要和其他屬性分開(kāi)來(lái)檢測(cè)嗎?

對(duì)于 toString 這樣的屬性被重寫(xiě),underscore 的判斷非常好,如果沒(méi)有被重寫(xiě),那么對(duì)象的 toString 方法肯定是繼承于原型鏈的,判斷對(duì)象的 toString 方法是否和原型鏈上的一致即可,但是用 hasOwnProperty 能判斷嗎?樓主覺(jué)得也是可以的,hasOwnProperty 方法用來(lái)判斷對(duì)象的 key 是否是自有屬性,即是否來(lái)自于原型鏈,如果被重寫(xiě)了,那么應(yīng)該會(huì)返回 true,否則 false。

而被重寫(xiě)的 constructor 能否用 obj[prop] !== proto[prop] 來(lái)判斷呢?樓主覺(jué)得也是可以的,如果沒(méi)有被重寫(xiě),那么 obj.constructor === obj.constructor.prototype.constructor 返回 true,如果被重寫(xiě),obj.constructor === Object.prototype.constructor 返回 false。

關(guān)于這點(diǎn),樓主也是百思不得其解,但是很顯然 constructor 屬性和其他屬性是有明顯區(qū)別的,從代碼理解角度來(lái)看,也是 underscore 這樣處理比較容易接受。如果是樓主理解有出入的地方,還望指出!

最后,小結(jié)下,對(duì)于 for ... in 在 IE < 9 下的兼容問(wèn)題,樓主感覺(jué)并沒(méi)有那么重要,畢竟誰(shuí)會(huì)沒(méi)事去重寫(xiě)這些屬性呢!所以,知道有這么一回事就可以了。

最后的最后,給出這部分源碼位置,有興趣的同學(xué)可以看下 https://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/src/underscore-1.8.3.js#L904-L946

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/79534.html

相關(guān)文章

  • underscore 源碼解讀】如何優(yōu)雅地寫(xiě)一個(gè)『在數(shù)組中尋找指定元素』方法

    摘要:今天要講的是,如何在數(shù)組中尋找元素,對(duì)應(yīng)中的,,,以及方法。如果往一個(gè)有序數(shù)組中插入元素,使得數(shù)組繼續(xù)保持有序,那么這個(gè)插入位置是這就是這個(gè)方法的作用,有序,很顯然用二分查找即可。 Why underscore (覺(jué)得這部分眼熟的可以直接跳到下一段了...) 最近開(kāi)始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計(jì)劃中。 閱讀一...

    0x584a 評(píng)論0 收藏0
  • underscore.js 源碼解讀】常用類(lèi)型判斷以及一些有用工具方法

    摘要:最近開(kāi)始看源碼,并將源碼解讀放在了我的計(jì)劃中。今天就跟大家聊一聊中一些常用類(lèi)型檢查方法,以及一些工具類(lèi)的判斷方法。用是否含有屬性來(lái)判斷工具類(lèi)判斷方法接下來(lái)看下一些常用的工具類(lèi)判斷方法。 Why underscore 最近開(kāi)始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計(jì)劃中。 閱讀一些著名框架類(lèi)庫(kù)的源碼,就好像和一個(gè)個(gè)大師對(duì)話(huà)...

    tanglijun 評(píng)論0 收藏0
  • 也談面試必備問(wèn)題之 JavaScript 數(shù)組去重

    摘要:而數(shù)組元素去重是基于運(yùn)算符的。而如果有迭代函數(shù),則計(jì)算傳入迭代函數(shù)后的值,對(duì)值去重,調(diào)用方法,而該方法的核心就是調(diào)用方法,和我們上面說(shuō)的方法一異曲同工。 Why underscore (覺(jué)得這部分眼熟的可以直接跳到下一段了...) 最近開(kāi)始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計(jì)劃中。 閱讀一些著名框架類(lèi)庫(kù)的源碼,就好像...

    Coly 評(píng)論0 收藏0
  • underscore 源碼解讀】Object Functions 相關(guān)源碼拾遺 & 小結(jié)

    摘要:直接來(lái)看例子一目了然,第一個(gè)參數(shù)是對(duì)象,第二個(gè)參數(shù)可以是一系列的值,也可以是數(shù)組數(shù)組中含,也可以是迭代函數(shù),我們根據(jù)值,或者迭代函數(shù)來(lái)過(guò)濾中的鍵值對(duì),返回新的對(duì)象副本。 Why underscore 最近開(kāi)始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計(jì)劃中。 閱讀一些著名框架類(lèi)庫(kù)的源碼,就好像和一個(gè)個(gè)大師對(duì)話(huà),你會(huì)學(xué)到很多。...

    neuSnail 評(píng)論0 收藏0
  • underscore 源碼解讀】Array Functions 相關(guān)源碼拾遺 & 小結(jié)

    摘要:最近開(kāi)始看源碼,并將源碼解讀放在了我的計(jì)劃中。將轉(zhuǎn)為數(shù)組同時(shí)去掉第一個(gè)元素之后便可以調(diào)用方法總結(jié)數(shù)組的擴(kuò)展方法就解讀到這里了,相關(guān)源碼可以參考這部分。放個(gè)預(yù)告,下一篇會(huì)暫緩下,講下相關(guān)的東西,敬請(qǐng)期待。 Why underscore 最近開(kāi)始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計(jì)劃中。 閱讀一些著名框架類(lèi)庫(kù)的源碼,就好...

    SimpleTriangle 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<