1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 7163字,需瀏覽 15分鐘

         ·

        2020-10-20 05:44


        前言

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

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

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

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

        API

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

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

        前往 —>?MDN[2]?學(xué)習(xí)基礎(chǔ)用法。

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

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

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

        forEach

        ?簡單實(shí)現(xiàn)

        // forEach 支持傳入兩個參數(shù),callback、thisArg// callback 返回3個參數(shù),當(dāng)前元素、當(dāng)前元素索引、原數(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ù)組的下標(biāo)并不一定是連續(xù)的          fn.call(context, arr[index], index, arr);      }      index ++;  }};

        ?支持 async/await


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

        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 的實(shí)現(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ù),有的話作為回調(diào)函數(shù)運(yùn)行的初始值        result = arg[1];    } else {        // reduce 在沒有第二個參數(shù)的時候,會把數(shù)組的第一項(xiàng)作為回調(diào)的初始值        // 第一項(xiàng)并不一定是 a[0]        while (index < len && !(index in arr)) {        // 下標(biāo)小于數(shù)組長度且下標(biāo)不屬于該數(shù)組就一直循環(huán),用來找到數(shù)組的第一項(xiàng)            index++;        }        if (index >= len) { // 如果第一項(xiàng)大于等于數(shù)組長度,則說明是空數(shù)組            throw new TypeError( '空數(shù)組且沒有初始值' );        }        result = arr[index++]; // 賦值之后下標(biāo)+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); // 每次回調(diào)的返回值,都會傳入下次回調(diào)        }        index ++;    }    return result;};

        reduce 實(shí)現(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]; // 如果返回值為真,就添加進(jìn)新數(shù)組        }        index ++;    }    return newArr;};

        find 和 findIndex

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

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

        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 在實(shí)現(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);    // 允許傳入負(fù)數(shù),意為從倒數(shù)第幾位開始查找    // 負(fù)數(shù)依然是按升序查找    // 避免傳入負(fù)數(shù)絕對值大于len而使k出現(xiàn)負(fù)數(shù),k設(shè)置最小值 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);    // 處理負(fù)數(shù)    while (k < len) {        if (k in arr) {            if (val === arr[k]) return k; // 找到返回下標(biāo)        }        k ++;    }    return -1; // 找不到返回 -1};

        join

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

        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;};

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


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


        瀏覽 33
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            亚洲人妻综合网 | 麻豆精品视频在线播放 | 在线播放亚洲无码 | 小草神被啪漫画禁漫天堂 | 美女黄频免费网站 | AV网站在线免费观看 | 一本一道无码免费看视频 | 中国女人毛片 | 韩国高清无码 | 国产精品 久久久精品岩 |