摘要:我們只能通過一些公開的參考一些瀏覽器內核公開代碼。但思路就在那了,更完善的代碼待大家來補充,一起交流。原創(chuàng)不簡單,碼字不易,點個贊,行不行
在日常 Coding 中,碼農(nóng)們肯定少不了對數(shù)組的操作,其中很常用的一個操作就是對數(shù)組進行遍歷,查看數(shù)組中的元素,然后一頓操作猛如虎。
就好像我們去買水果,在一堆水果中,一個一個看好壞。這個好,嗯,要,放入袋中;這個不好,不要,放回;這個好,嗯,呀 …
在我認識的眾多計算機語言中,如 Java、Python、JS,都有對 forEach 的實現(xiàn),今天暫且簡單地說說在 JavaScript 中 forEach。
學習或研究語言提供的函數(shù) API,一般都會有這么幾步:
看函數(shù)原型,理解參數(shù)
擼!實戰(zhàn),不斷驗證
深入源碼,看優(yōu)秀的代碼,實現(xiàn)方式
學習思想,模式
代碼很重要,但思維、認知更重要!
那么,不多說,先來看看 forEach 函數(shù)的原型:
/** * currentValue : 遍歷到的當前元素 * index : 當前元素的索引值 (可選) * arr : 當前元素所屬的數(shù)組對象,即 array (可選) * thisValue : 當執(zhí)行回調函數(shù)時用作 this 的值(參考對象) (可選) * * 返回值: undefined */ 1. array.forEach(function(currentValue, index, arr), thisArg); 2. arr.forEach(callback[, thisArg]);
這里有兩種函數(shù)原型的表達方式,第一種看起來稍微清楚明白點,第二種偏高大上,Linux 上很常見。看個人所接觸的語言及習慣,哪種適合自己,哪種能讓自己更容易理解、明白就看哪種就好,不必糾結!
適合自己的才是最好的!
其中 currentValue 就是遍歷到的當前元素,拿買蘋果作例子,我們從一堆蘋果中,一個個挑,而 currentValue 就是我們從水果堆中拿到的那個蘋果;
index 是當前元素的索引,也就是我們手中的蘋果是拿過的蘋果中是第幾個,比如這個是拿的我第二個,那 index 就是 1。為什么是 1 不是 2 呢 ?因為計算機語言是從 0 開始的,這是一個哲學問題;
arr 是當前元素所屬的數(shù)組對象,說白了就是那一堆蘋果。
而 thisArg,就很難解釋了。還是看例子吧,說千遍,不如做一步,自己敲一下,運行后,理解可能更深。
后面三個參數(shù)都是可選的,可有可無,估計他們很想哭。
來個栗子:
var array1 = ["a", "b", "c"]; var array2 = ["1","2","3"]; array1.forEach(function(currentValue, index, arr) { console.log(currentValue, index, arr, this); },array2); # 輸出 // 如果給 forEach() 傳遞了 thisArg 參數(shù),當調用時,它將被傳給 callback 函數(shù),作為它的 this 值。否則,將會傳入 undefined 作為它的 this 值 > "a" 0 ["a", "b", "c"] ["1", "2", "3"] > "b" 1 ["a", "b", "c"] ["1", "2", "3"] > "c" 2 ["a", "b", "c"] ["1", "2", "3"]
我們看到,數(shù)組的每一個元素及他們對應的索引被依次輸入,而 arr 就是它自己,而 this 則是 array2,是我們在調用 forEach 時傳進去的,在里面被當作 this 了。
源碼呢 ?
說到這,JavaScript 不像 Java 一樣,它提供的函數(shù)的源碼并不是用本身自己這種語言編寫的,而是用 C 或 C++ 寫的。這些函數(shù),其實只是一種對外公開的規(guī)范,就像是向開發(fā)提供的接口一樣。所以嚴格講,JavaScript 不是一門語言,而是一套規(guī)范,一套 API。
這與很多語言有著很大的不同。
對同一個函數(shù),或者說同一個 API,也有多種不同的方式實現(xiàn),因此,我們很難像 Java 一樣查看 forEach 的源碼,一個函數(shù),在同一個版本,源碼一致。
我們只能通過一些公開的參考一些瀏覽器內核公開代碼。
例如,mozilla 的 forEach 源碼:
/* ES5 15.4.4.18. */ function ArrayForEach(callbackfn/*, thisArg*/) { var O = ToObject(this); var len = ToLength(O.length); if (arguments.length === 0) ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Array.prototype.forEach"); if (!IsCallable(callbackfn)) ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); var T = arguments.length > 1 ? arguments[1] : void 0; for (var k = 0; k < len; k++) { if (k in O) { callContentFunction(callbackfn, T, O[k], k, O); } } return void 0; }
那我們能不能根據(jù)實際用途效果,參照前面的源碼,自己用 JavaScript 手寫一個 forEach 呢 ?
當然,可以!
我這里寫了兩種不同的 forEach 的實現(xiàn),如果你有更好的方式,歡迎貼代碼交流。
1.使用 call 方式
Array.prototype.forEach = function(callback,thisArg){ var len = this.length; for(var i = 0; i < len; i++){ // callback(this[i], i, this); callback.call(thisArg,this[i], i, this); } }
2.使用 bind 方式
Array.prototype.forEach = function(callback,thisArg){ var len = this.length; callback = callback.bind(thisArg); for(var i = 0; i < len; i++){ callback(this[i], i, this); } }
當然,代碼只給了關鍵性代碼,里面少了很多合理性判斷,特殊處理等。但思路就在那了,更完善的代碼待大家來補充,一起交流。
原創(chuàng)不簡單,碼字不易,點個贊,行不行 !
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/104338.html
摘要:輔助方法這個方法遞歸遍歷的子節(jié)點,將節(jié)點交由回調函數(shù)處理。對集合進行遍歷,調用方法,如果為函數(shù),則將回調函數(shù)返回的結果作為參數(shù)傳給否則,如果為,則將也即包裹元素的副本傳給,否則直接將傳給。 這篇依然是跟 dom 相關的方法,側重點是操作 dom 的方法。 讀Zepto源碼系列文章已經(jīng)放到了github上,歡迎star: reading-zepto 源碼版本 本文閱讀的源碼為 zepto...
摘要:源碼架構圖調用鏈路請求調用流程存放方法指定的參數(shù)的中間件存放實例存放路徑參數(shù)的一些屬性,存放該路由的中間件如果支持請求,一并支持請求將路由轉為正則表達式給實例掛載方法如果指定了路由屬性路由注冊實例數(shù)組,初始為空數(shù) 源碼架構圖 showImg(https://segmentfault.com/img/bVbgy2f?w=1159&h=1495); 調用鏈路-routes() showIm...
摘要:先看下圖,我們以刪除元素,插入元素復制元素,包裹元素和替換元素幾個模塊分別探究如何一一將其實現(xiàn)。遍歷當前集合中的元素,當該元素的父節(jié)點存在的時候,使用刪除該元素。接下來我們來看如何將中創(chuàng)建好的節(jié)點插入到目標位置。 前言 dom也就是文檔對象模型,是針對HTML和XML的一個api,描繪了一個層次化的節(jié)點樹。雖然瀏覽器原生給我們提供了許多操作dom的方法,使我們可以對dom進行查找,復制...
摘要:先看下圖,我們以刪除元素,插入元素復制元素,包裹元素和替換元素幾個模塊分別探究如何一一將其實現(xiàn)。遍歷當前集合中的元素,當該元素的父節(jié)點存在的時候,使用刪除該元素。接下來我們來看如何將中創(chuàng)建好的節(jié)點插入到目標位置。 前言 dom也就是文檔對象模型,是針對HTML和XML的一個api,描繪了一個層次化的節(jié)點樹。雖然瀏覽器原生給我們提供了許多操作dom的方法,使我們可以對dom進行查找,復制...
摘要:先看下圖,我們以刪除元素,插入元素復制元素,包裹元素和替換元素幾個模塊分別探究如何一一將其實現(xiàn)。遍歷當前集合中的元素,當該元素的父節(jié)點存在的時候,使用刪除該元素。接下來我們來看如何將中創(chuàng)建好的節(jié)點插入到目標位置。 前言 dom也就是文檔對象模型,是針對HTML和XML的一個api,描繪了一個層次化的節(jié)點樹。雖然瀏覽器原生給我們提供了許多操作dom的方法,使我們可以對dom進行查找,復制...
閱讀 1246·2021-09-04 16:41
閱讀 2403·2021-09-02 10:18
閱讀 917·2019-08-29 16:40
閱讀 2614·2019-08-29 16:14
閱讀 898·2019-08-26 13:41
閱讀 1299·2019-08-26 12:24
閱讀 731·2019-08-26 10:24
閱讀 2869·2019-08-23 17:54