摘要:直接來看例子一目了然,第一個參數(shù)是對象,第二個參數(shù)可以是一系列的值,也可以是數(shù)組數(shù)組中含,也可以是迭代函數(shù),我們根據(jù)值,或者迭代函數(shù)來過濾中的鍵值對,返回新的對象副本。
Why underscore
最近開始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計劃中。
閱讀一些著名框架類庫的源碼,就好像和一個個大師對話,你會學(xué)到很多。為什么是 underscore?最主要的原因是 underscore 簡短精悍(約 1.5k 行),封裝了 100 多個有用的方法,耦合度低,非常適合逐個方法閱讀,適合樓主這樣的 JavaScript 初學(xué)者。從中,你不僅可以學(xué)到用 void 0 代替 undefined 避免 undefined 被重寫等一些小技巧 ,也可以學(xué)到變量類型判斷、函數(shù)節(jié)流&函數(shù)去抖等常用的方法,還可以學(xué)到很多瀏覽器兼容的 hack,更可以學(xué)到作者的整體設(shè)計思路以及 API 設(shè)計的原理(向后兼容)。
之后樓主會寫一系列的文章跟大家分享在源碼閱讀中學(xué)習(xí)到的知識。
underscore-1.8.3 源碼解讀項(xiàng)目地址 https://github.com/hanzichi/underscore-analysis
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 源碼解讀系列文章 https://github.com/hanzichi/underscore-analysis/issues
歡迎圍觀~ (如果有興趣,歡迎 star & watch~)您的關(guān)注是樓主繼續(xù)寫作的動力
Main趁著今天是工作日的最后一天,把源碼解讀部分 Object Functions 更新完畢。
如果你有心,可能就會發(fā)現(xiàn)樓主之前的解讀系列文章說的都是 Object 上的擴(kuò)展方法,也就是源碼中 Object Functions 部分。underscore 為 5 種類型添加了擴(kuò)展方法,分別是 Object -> Array -> Collection -> Function -> Utility,這也正是樓主的源碼解讀順序(并不是源碼順序)。其中,Object 上的擴(kuò)展方法多達(dá) 38 個,方法多并不代表代碼多,比如類型檢測,兩行代碼就可以搞定好幾個方法,而上一篇中說的 _.isEqual 方法,卻要百來行去實(shí)現(xiàn)。今天是 Object Functions 部分的最后一篇,我們來看看樓主認(rèn)為的幾個沒被解讀過的但是卻有意思的方法的源碼。(其實(shí)很多方法使用簡單,實(shí)現(xiàn)也非常簡單,有興趣的同學(xué)可以自己扒下源碼)
_.pick首先來看看 _.pick 方法,該方法傳入一個對象,然后刪選對象的鍵值對,返回一個對象副本。
直接來看例子:
_.pick({name: "moe", age: 50, userid: "moe1"}, "name", "age"); => {name: "moe", age: 50} _.pick({name: "moe", age: 50, userid: "moe1"}, ["name", "age"]); => {name: "moe", age: 50} _.pick({name: "moe", age: 50, userid: "moe1"}, function(value, key, object) { return _.isNumber(value); }); => {age: 50}
一目了然,第一個參數(shù) obj 是對象,第二個參數(shù)可以是一系列的 key 值,也可以是數(shù)組(數(shù)組中含 key),也可以是迭代函數(shù),我們根據(jù) key 值,或者迭代函數(shù)來過濾 obj 中的鍵值對,返回新的對象副本。
如果讓我來設(shè)計,估計會根據(jù)參數(shù)來判斷類型,然后寫幾個 if-else,每個 if-else 分支里的內(nèi)容毫無關(guān)聯(lián)。但是 underscore 的寫法簡直美妙,將幾種情況轉(zhuǎn)為了一種。
// 如果第二個參數(shù)是函數(shù) if (_.isFunction(oiteratee)) { keys = _.allKeys(obj); iteratee = optimizeCb(oiteratee, context); }
首先 if-else 是不可避免的,如果傳入的第二個參數(shù)是 function,那么就是傳入迭代函數(shù)了,根據(jù) context(this)返回新的迭代函數(shù)(optimizeCb 我以后會講,就是規(guī)定了迭代函數(shù)中的 this 指向,不是很重要,這里可以選擇性忽略)。
如果第二個參數(shù)不是函數(shù),則后面的 keys 可能是數(shù)組,也可能是連續(xù)的幾個并列的參數(shù)。這里我們要用到 underscore 中另一個重要的內(nèi)部方法,flatten,它的作用是將嵌套的數(shù)組展開,這個方法我以后會分析,這里知道它的作用就可以了。
else { // 如果第二個參數(shù)不是函數(shù) // 則后面的 keys 可能是數(shù)組 // 也可能是連續(xù)的幾個并列的參數(shù) keys = flatten(arguments, false, false, 1); // 也轉(zhuǎn)為 predicate 函數(shù)判斷形式 // 將指定 key 轉(zhuǎn)化為 predicate 函數(shù) iteratee = function(value, key, obj) { return key in obj; }; obj = Object(obj); }
也轉(zhuǎn)為和傳入迭代函數(shù)一樣的形式,就可以用一個方法判斷了,而且 keys 變量在兩種情況下的意義是不同的,真的非常巧妙。這點(diǎn)令我思考良多,很多時候的代碼冗余,其實(shí)大概是自己代碼能力太差了吧,打死我也想不到這樣做。
_.create_.create 方法非常簡單,根據(jù)你給的原型(prototype),以及一些 own properties,構(gòu)造新的對象返回。
舉個簡單的例子:
var Person = function() {}; Person.prototype = { show: function() { alert(this.name); } }; var me = _.create(Person.prototype, {name: "hanzichi"}); console.log(me); // Object {name: "hanzichi"} // name: "hanzichi" // __proto__: Object // show: function()
其實(shí) me 變量就是一個擁有 name 作為 own properties,且用 Person 函數(shù)構(gòu)造的對象。
如果瀏覽器支持 ES5,我們可以用 Object.create():
var Person = function() {}; Person.prototype = { show: function() { alert(this.name); } }; var me = Object.create(Person.prototype); _.extendOwn(me, {name: "hanzichi"}); console.log(me);
如果不支持 ES5,我們可以新定義一個構(gòu)造函數(shù),將該構(gòu)造函數(shù)的 prototype 賦值為已知的 prototype 變量,然后用 new 運(yùn)算符來獲取實(shí)例:
var Person = function() {}; Person.prototype = { show: function() { alert(this.name); } }; var _Person = function() {}; _Person.prototype = Person.prototype; var me = new _Person(); _.extendOwn(me, {name: "hanzichi"}); console.log(me);
undercore 的實(shí)現(xiàn)思路也大抵如此。
_.tap本來打算把 _.tap 講掉,突然覺得跟鏈?zhǔn)秸{(diào)用一起講比較好,挖個坑。
小結(jié)關(guān)于 Objects Function 部分的源碼剖析就到這了,具體這部分代碼可以參考 https://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/src/underscore-1.8.3.js#L901-L1269。雖然說看完了這部分代碼,但是要真正理解消化還是需要時間的,我只能說自己理解了 90% 左右,歡迎探討交流。
接下去應(yīng)該會著手看 Array 擴(kuò)展方法相關(guān)代碼,繼續(xù)為大家整理有意思的東西,各種奇淫怪巧,敬請期待。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/79572.html
摘要:最近開始看源碼,并將源碼解讀放在了我的計劃中。將轉(zhuǎn)為數(shù)組同時去掉第一個元素之后便可以調(diào)用方法總結(jié)數(shù)組的擴(kuò)展方法就解讀到這里了,相關(guān)源碼可以參考這部分。放個預(yù)告,下一篇會暫緩下,講下相關(guān)的東西,敬請期待。 Why underscore 最近開始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計劃中。 閱讀一些著名框架類庫的源碼,就好...
摘要:支持形式的調(diào)用這其實(shí)是非常經(jīng)典的無構(gòu)造,其實(shí)就是一個構(gòu)造函數(shù),的結(jié)果就是一個對象實(shí)例,該實(shí)例有個屬性,屬性值是。 前言 終于,樓主的「Underscore 源碼解讀系列」underscore-analysis 即將進(jìn)入尾聲,關(guān)注下 timeline 會發(fā)現(xiàn)樓主最近加快了解讀速度。十一月,多事之秋,最近好多事情搞的樓主心力憔悴,身心俱疲,也想盡快把這個系列完結(jié)掉,也好了卻一件心事。 本文...
摘要:今天要講的是,如何在數(shù)組中尋找元素,對應(yīng)中的,,,以及方法。如果往一個有序數(shù)組中插入元素,使得數(shù)組繼續(xù)保持有序,那么這個插入位置是這就是這個方法的作用,有序,很顯然用二分查找即可。 Why underscore (覺得這部分眼熟的可以直接跳到下一段了...) 最近開始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計劃中。 閱讀一...
摘要:最近開始看源碼,并將源碼解讀放在了我的計劃中。像和使用內(nèi)置構(gòu)造函數(shù)所創(chuàng)建的對象都會繼承自和的不可枚舉屬性,例如的方法或者的方法。循環(huán)將迭代對象的所有可枚舉屬性和從它的構(gòu)造函數(shù)的繼承而來的包括被覆蓋的內(nèi)建屬性。 Why underscore 最近開始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計劃中。 閱讀一些著名框架類庫的源碼...
摘要:最近開始看源碼,并將源碼解讀放在了我的計劃中。今天就跟大家聊一聊中一些常用類型檢查方法,以及一些工具類的判斷方法。用是否含有屬性來判斷工具類判斷方法接下來看下一些常用的工具類判斷方法。 Why underscore 最近開始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計劃中。 閱讀一些著名框架類庫的源碼,就好像和一個個大師對話...
閱讀 1867·2021-11-25 09:43
閱讀 3694·2021-11-24 10:32
閱讀 1089·2021-10-13 09:39
閱讀 2341·2021-09-10 11:24
閱讀 3355·2021-07-25 21:37
閱讀 3477·2019-08-30 15:56
閱讀 871·2019-08-30 15:44
閱讀 1460·2019-08-30 13:18