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