<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          「前端練習場」原生 JavaScript 手寫各種 數(shù)組 API

          共 7163字,需瀏覽 15分鐘

           ·

          2020-10-20 05:44


          前言

          JavaScript 中的數(shù)組類型提供了很多原生方法供我們使用,本文會?模擬實現(xiàn)?一些常用的數(shù)組 API。

          「前端練習場」?將會持續(xù)更新,不同于之前的?【前端進階之路】?和?【從頭到腳】?這兩個系列,練習場?主要側重于基礎知識的練習鞏固,大家對這個系列有好的建議也可以在評論區(qū)和我交流 ? 。

          另外我自己也是在不斷的學習中,如果有不對的地方麻煩大家斧正,我會及時更新,感謝。

          博客地址??? fe-code[1]

          API

          數(shù)組的 API 有很多,我這里放一些常用的。如果大家有其他的實現(xiàn)方法,可以放在評論區(qū),我看到了會更新到文章中 ^_^。`

          本文不是具體講某個 API 的基本用法,所以對這些 API 用法不太熟悉的同學需要先自行學習。另外大部分實現(xiàn),在 MDN 上都有。

          前往 —>?MDN[2]?學習基礎用法。

          在正式開始實現(xiàn)之前,先看一個例子。

          let arr = [];arr[3] = 3;// arr.length ? arr[0] ?  0 in arr ?
          // 4 undefined fasle

          這個東西在后面的實現(xiàn)中會出現(xiàn),所以大家先了解一下。數(shù)組的下標不一定是連續(xù)的,直接賦值還會影響它的長度。

          forEach

          ?簡單實現(xiàn)

          // forEach 支持傳入兩個參數(shù),callback、thisArg// callback 返回3個參數(shù),當前元素、當前元素索引、原數(shù)組// thisArg 傳入后,改變 callback 的 this 指針Array.prototype.myforeach = function (fn, context = null) {  let index = 0;  let arr = this;  if (typeof fn !== 'function') {      throw new TypeError(fn + ' is not a function');  }  while (index < arr.length) {      if (index in arr) { // 數(shù)組的下標并不一定是連續(xù)的          fn.call(context, arr[index], index, arr);      }      index ++;  }};

          ?支持 async/await


          之前見大佬們討論過這個問題,所以提一下。forEach 在正常情況像下面這么寫肯定是做不到同步的,程序不會等一個循環(huán)中的異步完成再進行下一個循環(huán)。原因很明顯,在上面的模擬中,while 循環(huán)只是簡單執(zhí)行了 callback,所以盡管 callback 內使用了 await ,也只是影響到 callback 內部。

          arr.myforeach(async v => {    await fetch(v);});

          要支持上面這種寫法,只要稍微改一下就好。

          Array.prototype.myforeach = async function (fn, context = null) {    let index = 0;    let arr = this;    if (typeof fn !== 'function') {        throw new TypeError(fn + ' is not a function');    }    while (index < arr.length) {        if (index in arr) {            try {                await fn.call(context, arr[index], index, arr);            } catch (e) {                console.log(e);            }        }        index ++;    }};

          map

          map 的實現(xiàn)大體和 forEach 類似,只是返回了一個新數(shù)組。

          // 參數(shù)和forEach一樣// callback 需要有一個返回值Array.prototype.mymap = function (fn, context = null) {    let arr = this;    let len = arr.length;    let index = 0;    let newArr = [];    if (typeof fn !== 'function') {        throw new TypeError(fn + ' is not a function');    }    while (index < len) {        if (index in arr) {            let result = fn.call(context, arr[index], index, arr);            newArr[index] = result; // 返回值作為一個新數(shù)組        }        index ++;    }    return newArr;};

          reduce

          reduce 稍微麻煩一些,需要根據(jù)第二個參數(shù)是否存在,使用不同的處理方式。

          Array.prototype.myreduce = function (...arg) {    let arr = this;    let len = arr.length;    let index = 0;    let fn = arg[0], result;    if (arg.length >= 2) { // 判斷是否有第二個參數(shù),有的話作為回調函數(shù)運行的初始值        result = arg[1];    } else {        // reduce 在沒有第二個參數(shù)的時候,會把數(shù)組的第一項作為回調的初始值        // 第一項并不一定是 a[0]        while (index < len && !(index in arr)) {        // 下標小于數(shù)組長度且下標不屬于該數(shù)組就一直循環(huán),用來找到數(shù)組的第一項            index++;        }        if (index >= len) { // 如果第一項大于等于數(shù)組長度,則說明是空數(shù)組            throw new TypeError( '空數(shù)組且沒有初始值' );        }        result = arr[index++]; // 賦值之后下標+1    }    if (typeof fn !== 'function') {        throw new TypeError(fn + ' is not a function');    }    while (index < len) {        if (index in arr) {            result = fn(result, arr[index], index, arr); // 每次回調的返回值,都會傳入下次回調        }        index ++;    }    return result;};

          reduce 實現(xiàn)一個 map

          經(jīng)常會有面試問到這道題,順便寫一下。

          Array.prototype.mapByreduce = function (fn, context = null) {    let arr = this;    if (typeof fn !== 'function') {         throw new TypeError(fn + ' is not a function');    }    return arr.reduce((pre, cur, index, array) => {        let res = fn.call(context, cur, index, array);        return [...pre, res]; // 返回一個新數(shù)組    }, []);};

          filter

          filter 一般用來篩選。

          Array.prototype.myfilter = function (fn, context = null) {    let arr = this;    let len = arr.length;    let index = 0, k = 0;    let newArr = [];    if (typeof fn !== 'function') {        throw new TypeError(fn + ' is not a function');    }    while (index < len) {        if (index in arr) {            let result = fn.call(context, arr[index], index, arr);            if (result) newArr[k++] = arr[index]; // 如果返回值為真,就添加進新數(shù)組        }        index ++;    }    return newArr;};

          find 和 findIndex

          find 和 filter 很類似,找到一個就返回當前元素,找不到返回 undefined。

          findIndex 找到返回下標,找不到返回 -1。和 indexOf 類似,區(qū)別是支持回調。

          Array.prototype.myfind = function (fn, context = null) {    let arr = this;    let len = arr.length;    let index = 0;    if (typeof fn !== 'function') {        throw new TypeError(fn + ' is not a function');    }    while (index < len) {        if (index in arr) {            let result = fn.call(context, arr[index], index, arr);            if (result) return arr[index]; // 滿足條件就返回        }        index ++;    }    return undefined;};

          some

          some 和 find,除了返回值有區(qū)別,其他的可以說都一樣。

          Array.prototype.mysome = function (fn, context = null) {    let arr = this;    let len = arr.length;    let index = 0;    if (typeof fn !== 'function') {        throw new TypeError(fn + ' is not a function');    }    while (index < len) {        if (index in arr) {            let result = fn.call(context, arr[index], index, arr);            if (result) return true; // 找到一個滿足的,立即返回true        }        index ++;    }    return false; // 找不到返回 false};

          every

          跟 some 相比,每個成員都滿足條件才返回 true,有一個不滿足就返回 false。

          Array.prototype.myevery = function (fn, context = null) {    let arr = this;    let len = arr.length;    let index = 0;    if (typeof fn !== 'function') {        throw new TypeError(fn + ' is not a function');    }    while (index < len) {        if (index in arr) {            let result = fn.call(context, arr[index], index, arr);            if (!result) return false; // 有一個不滿足,就返回false        }        index ++;    }    return true;};

          剛剛接連幾個 filter、find、some、every 在實現(xiàn)和功能上都很相似,只是返回值上有一些差別,所以更要在合適的場景使用合適的方法。

          includes 和 indexOf

          這兩個都可以用來查找數(shù)組中是否有某個元素,只是返回值有區(qū)別。

          Array.prototype.myincludes = function (val, fromIndex = 0) {    let arr = this;    let len = arr.length;    let k = Math.max(fromIndex >= 0 ? fromIndex : len - Math.abs(fromIndex), 0);    // 允許傳入負數(shù),意為從倒數(shù)第幾位開始查找    // 負數(shù)依然是按升序查找    // 避免傳入負數(shù)絕對值大于len而使k出現(xiàn)負數(shù),k設置最小值 0     function check(x, y) {        return x === y ||        (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));        // 判斷 NaN    }    while (k < len) {        if (k in arr) {            if (check(val, arr[k])) return true; // 找到一個符合條件的,返回 true        }        k ++;    }    return false; // 沒找到 返回false};
          // indexOf 不支持查找 NaN Array.prototype.myindexOf = function (val, fromIndex = 0) {    let arr = this;    let len = arr.length;    let k = Math.max(fromIndex >= 0 ? fromIndex : len - Math.abs(fromIndex), 0);    // 處理負數(shù)    while (k < len) {        if (k in arr) {            if (val === arr[k]) return k; // 找到返回下標        }        k ++;    }    return -1; // 找不到返回 -1};

          join

          使用連接符,將數(shù)組轉成字符串

          Array.prototype.myjoin = function (connector = ',') {    let arr = this;    let len = arr.length;    let str = '';    let k = 0;    while (k < len) {        if (k in arr) {            if (k === len -1) { // 最后一位不用連接                str += arr[k];            } else {                str += arr[k] + connector.toString();            }        }        k ++;    }    return str;};

          好了,大致就寫這些,如果大家覺得有必要補充的可以跟我說。


          如果你喜歡探討技術,或者對本文有任何的意見或建議,非常歡迎加魚頭微信好友一起探討,當然,魚頭也非常希望能跟你一起聊生活,聊愛好,談天說地。魚頭的微信號是:krisChans95 也可以掃碼關注公眾號,訂閱更多精彩內容。


          瀏覽 33
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲黑人无码在线观看 | 成人无码一级A片在线 | 91在线成人传媒 | 99精品操 | 插菊花日本加勒比色综合网 |