摘要:前面的的目的在于利用自定義拋出錯(cuò)誤令遍歷停止如果是數(shù)組直接過濾輸出不是數(shù)組遍歷操作壓入數(shù)組返回有點(diǎn)像,過濾符合條件的注意感嘆號(hào)取反有點(diǎn)像設(shè)置默認(rèn)迭代器判斷是否存在即需要所有元素都滿足迭代條件。
前言
這篇文章是為之后的underscore現(xiàn)版本的源碼做鋪墊,先感受下最先版本
0.1.0版本足夠小
這個(gè)版本已經(jīng)有將近小10年的歷史了
還是有一些不錯(cuò)的地方。
0.1.0版本源碼分析
// Underscore.js // (c) 2009 Jeremy Ashkenas, DocumentCloud Inc. // Underscore is freely distributable under the terms of the MIT license. // Portions of Underscore are inspired by or borrowed from Prototype.js, // Oliver Steele"s Functional, And John Resig"s Micro-Templating. // For all details and documentation: // http://documentcloud.github.com/underscore/ window._ = { VERSION : "0.1.0", /*------------------------ Collection Functions: ---------------------------*/ // 集合函數(shù) // The cornerstone, an each implementation. // Handles objects implementing forEach, each, arrays, and raw objects. each : function(obj, iterator, context) { var index = 0; try { if (obj.forEach) { // 有forEach優(yōu)先選擇forEach obj.forEach(iterator, context); } else if (obj.length) { // 使用自定義迭代器迭代 for (var i=0; i總結(jié)= result.computed) result = {value : value, computed : computed}; // 對(duì)初始化以及每一次判斷computed大于當(dāng)前值更新 }); return result.value; }, // Return the minimum element (or element-based computation). min : function(obj, iterator, context) { if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj); var result; _.each(obj, function(value, index) { var computed = iterator ? iterator.call(context, value, index) : value; if (result == null || computed < result.computed) result = {value : value, computed : computed}; }); return result.value; }, // Sort the object"s values by a criteria produced by an iterator. sortBy : function(obj, iterator, context) { // 根據(jù)對(duì)象的一些值進(jìn)行排序 // 首先我們只要關(guān)注每個(gè)函數(shù)的目的即可 // map一次遍歷,返回多個(gè)對(duì)象數(shù)組。然后根據(jù)數(shù)組對(duì)象排序 // 并且對(duì)象均有值為criteria表示我們迭代函數(shù)的值(就是根據(jù)什么排序) return _.pluck(_.map(obj, function(value, index) { return { value : value, criteria : iterator.call(context, value, index) }; }).sort(function(left, right) { var a = left.criteria, b = right.criteria; // 判斷大于小于等于 return a < b ? -1 : a > b ? 1 : 0; }), "value"); // 外面的一層pluck是為了解開map函數(shù)的一層打包 }, // Use a comparator function to figure out at what index an object should // be inserted so as to maintain order. Uses binary search. // 這是利用二分查找吧 // 利用二分查找找出元素應(yīng)該插入到哪個(gè)位置中 sortedIndex : function(array, obj, iterator) { iterator = iterator || function(val) { return val; }; // 初始化一個(gè)迭代器 var low = 0, high = array.length;//不嚴(yán)謹(jǐn)直接去length // 初始化高低位 // while (low < high) { var mid = (low + high) >> 1; // 對(duì)中位取半(important快捷方法) iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid; } return low; }, // Convert anything iterable into a real, live array. // 轉(zhuǎn)換數(shù)組(轉(zhuǎn)換一切可迭代的) toArray : function(iterable) { if (!iterable) return []; //為假值直接返回[] if (_.isArray(iterable)) return iterable; //判斷是否為數(shù)組 return _.map(iterable, function(val){ return val; });//如果為對(duì)象的話,利用map轉(zhuǎn)成數(shù)組 }, // Return the number of elements in an object. // 返回對(duì)象的元素?cái)?shù)量 size : function(obj) { return _.toArray(obj).length; }, /*-------------------------- Array Functions: ------------------------------*/ // Get the first element of an array. // 返回?cái)?shù)組第一個(gè)元素 first : function(array) { return array[0]; }, // Get the last element of an array. // 返回?cái)?shù)組最后一個(gè)元素 last : function(array) { return array[array.length - 1]; }, // Trim out all falsy values from an array. //去除假值的數(shù)組元素 //需要傳入一個(gè)操作函數(shù) false值在兩次取反會(huì)被去掉 compact : function(array) { return _.select(array, function(value){ return !!value; }); }, // Return a completely flattened version of an array. //多維數(shù)組返回一個(gè)一維數(shù)組 // 數(shù)組扁平化 // 開始展現(xiàn)出函數(shù)式編程的靈活性了 flatten : function(array) { return _.inject(array, [], function(memo, value) { // 這邊如果還是數(shù)組的話進(jìn)行一個(gè)遞歸的扁平 if (_.isArray(value)) return memo.concat(_.flatten(value)); memo.push(value); return memo; }); }, // Return a version of the array that does not contain the specified value(s). // 對(duì)傳入的數(shù)組進(jìn)行篩選 // 這里有一個(gè)點(diǎn),我們?cè)趥鲄⑿螀⒍x了array // 而在下面的地方我們可以直接使用array且slice截取arguments without : function(array) { var values = array.slice.call(arguments, 0); return _.select(array, function(value){ return !_.include(values, value); }); }, // Produce a duplicate-free version of the array. If the array has already // been sorted, you have the option of using a faster algorithm. // 唯一的數(shù)組。有一個(gè)參數(shù)可以選擇是否排序的數(shù)組,是的話會(huì)選擇最快的算法 uniq : function(array, isSorted) { return _.inject(array, [], function(memo, el, i) { if (0 == i || (isSorted ? _.last(memo) != el : !_.include(memo, el))) memo.push(el); return memo; }); }, // Produce an array that contains every item shared between all the // passed-in arrays. // 篩選多個(gè)元素?cái)?shù)組的相同值 intersect : function(array) { var rest = _.toArray(arguments).slice(1); // 獲得其余多個(gè)參數(shù) // 最外面肯定是一層篩選。 // 里面做篩選的條件 return _.select(_.uniq(array), function(item) { return _.all(rest, function(other) { // 目的在于取交集 // 所以我們使用外層的item 對(duì)比層的個(gè)個(gè)數(shù)組 據(jù)此我們返回同時(shí)存在多個(gè)數(shù)組中的元素 return _.indexOf(other, item) >= 0; }); }); }, // Zip together multiple lists into a single array -- elements that share // an index go together. zip : function() { var args = _.toArray(arguments); var length = _.max(_.pluck(args, "length")); // 返回最大數(shù)組的長(zhǎng)度。 var results = new Array(length); // 創(chuàng)建一個(gè)存放點(diǎn) for (var i=0; i 提取替換 var fn = new Function("obj", "var p=[],print=function(){p.push.apply(p,arguments);};" + "with(obj){p.push("" + str .replace(/[ ]/g, " ") .split("<%").join(" ") .replace(/((^|%>)[^ ]*)"/g, "$1 ") .replace(/ =(.*?)%>/g, "",$1,"") .split(" ").join("");") .split("%>").join("p.push("") .split(" ").join(""") + "");}return p.join("");"); return data ? fn(data) : fn; } };
后面的模板實(shí)現(xiàn)挺亮眼。
try catch 設(shè)計(jì)each的跳出。
>> 取半的快捷
函數(shù)的復(fù)用。(有部分也許是不高效)
整個(gè)版本時(shí)間很前。所以我們可以從中看到一些現(xiàn)代api的影子,也許是在現(xiàn)代api中看到它們的影子。
源碼篇幅較少,加上注釋也不過400行左右。整篇閱讀下來也沒有很大的障礙,就是有復(fù)用性相對(duì)較高,但是對(duì)著test文件看看測(cè)試用例也就好了~~~
可以通過這些地方聯(lián)系我我的博客
我的郵箱:kang95630@gmail.com
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/93320.html
摘要:最近開始看源碼,并將源碼解讀放在了我的計(jì)劃中。相對(duì)于其他源碼解讀的文章,基本都會(huì)從整體設(shè)計(jì)開始講起,樓主覺得這個(gè)庫(kù)有點(diǎn)特殊,決定按照自己的思路,從用代替說起。源碼沒有出現(xiàn)注意,其實(shí)有出現(xiàn)一處,是為,而不是,而用代替之。 Why underscore 最近開始看 underscore源碼,并將 underscore源碼解讀 放在了我的 2016計(jì)劃 中。 閱讀一些著名框架類庫(kù)的源碼,就好...
摘要:所以它與其他系列的文章并不沖突,完全可以在閱讀完這個(gè)系列后,再跟著其他系列的文章接著學(xué)習(xí)。如何閱讀我在寫系列的時(shí)候,被問的最多的問題就是該怎么閱讀源碼我想簡(jiǎn)單聊一下自己的思路。感謝大家的閱讀和支持,我是冴羽,下個(gè)系列再見啦 前言 別名:《underscore 系列 8 篇正式完結(jié)!》 介紹 underscore 系列是我寫的第三個(gè)系列,前兩個(gè)系列分別是 JavaScript 深入系列、...
摘要:開始研究核心代碼這個(gè)類首先是構(gòu)造函數(shù)看完上面的內(nèi)容大家應(yīng)該有點(diǎn)印象,上掛了和,是默認(rèn)的配置,顧名思義就是攔截器,目測(cè)包含了和兩種類型。喜歡就點(diǎn)個(gè)贊吧參考文章源代碼重點(diǎn)難點(diǎn)分析源代碼重點(diǎn)難點(diǎn)分析 axios是一個(gè)基于promise的http庫(kù),支持瀏覽器和node端,最近我在做beauty-we的api設(shè)計(jì),研讀一個(gè)成熟的http庫(kù)勢(shì)在必行,axios功能完整、api簡(jiǎn)潔、注釋清晰,再適...
摘要:此次源碼分析為以前曾讀過一次,可是沒有做下筆記。類似的兼容寫法記錄版本號(hào)優(yōu)化回調(diào)特指函數(shù)中傳入的回調(diào)是一個(gè)真正的因?yàn)槭强梢员毁x值的防止值被篡改接下來就是保證回調(diào)函數(shù)的執(zhí)行上下文。 此次源碼分析為 1.8.3 version 以前曾讀過一次,可是沒有做下筆記。此次重新閱讀特制此筆記 Baseline setup underscore是包裹在一個(gè)閉包內(nèi)部的防止污染全局變量 (functio...
摘要:作者韓子遲不知不覺間,源碼解讀系列進(jìn)入了真正的尾聲,也請(qǐng)?jiān)试S我最后一次下項(xiàng)目的原始地址這半年以來,花費(fèi)了大量的業(yè)余時(shí)間,共計(jì)寫了篇隨筆包括此文,也給的源碼加了差不多行注釋,對(duì)于當(dāng)初說的要做史上最詳細(xì)的源碼剖析,至此我也覺得問心無愧。 作者:韓子遲 What? 不知不覺間,「Underscore 源碼解讀系列」進(jìn)入了真正的尾聲,也請(qǐng)?jiān)试S我最后一次 po 下項(xiàng)目的原始地址 https://...
閱讀 1907·2021-09-23 11:21
閱讀 1693·2019-08-29 17:27
閱讀 1053·2019-08-29 17:03
閱讀 719·2019-08-29 15:07
閱讀 1916·2019-08-29 11:13
閱讀 2374·2019-08-26 12:14
閱讀 904·2019-08-26 11:52
閱讀 1730·2019-08-23 17:09