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>

        深入理解擴(kuò)展運(yùn)算符實(shí)現(xiàn)原理

        共 4768字,需瀏覽 10分鐘

         ·

        2021-05-17 14:34

        點(diǎn)擊上方 前端Q,關(guān)注公眾號(hào)

        回復(fù)加群,加入前端Q技術(shù)交流群

        ... 作用

        擴(kuò)展運(yùn)算符(spread)是三個(gè)點(diǎn)(...),用于取出參數(shù)對(duì)象中的所有可遍歷屬性,淺拷貝到當(dāng)前對(duì)象之中。

        常見用法

        1. 淺拷貝數(shù)組
        const a1 = ['test1''test2'];
        const a2 = [...a1];

        a2[0] = 'test2';
        a2 // ['test2', 'test2']
        1. 合并數(shù)據(jù)
        const arr1 = ['a''b'];
        const arr2 = ['c'];
        const arr3 = ['d''e'];

        // ES5 的合并數(shù)組
        arr1.concat(arr2, arr3);
        // [ 'a', 'b', 'c', 'd', 'e' ]

        // ES6 的合并數(shù)組
        [...arr1, ...arr2, ...arr3]
        // [ 'a', 'b', 'c', 'd', 'e' ]
        1. 解構(gòu)賦值
        const [first, ...rest] = [12345];
        first // 1
        rest  // [2, 3, 4, 5]

        const [first, ...rest] = [];
        first // undefined
        rest  // []

        const [first, ...rest] = ["foo"];
        first  // "foo"
        rest   // []
        1. 字符串/類數(shù)組轉(zhuǎn)為真正的數(shù)組

        因?yàn)槿魏味x了遍歷器(Iterator)接口的對(duì)象,都可以用擴(kuò)展運(yùn)算符轉(zhuǎn)為真正的數(shù)組。

        [...'test']
        // [ "t", "e", "s", "t"]

        [...document.querySelectorAll('div')]
        // [<div>, <div>, <div>]

        基本實(shí)現(xiàn)原理

        如果不用 ...,如何實(shí)現(xiàn)一樣的功能?由上面的用法,可以知道。擴(kuò)展運(yùn)算符主要就是淺拷貝可遍歷對(duì)象屬性,那么我們可以用es5的寫法實(shí)現(xiàn)如下:

        // 簡單版實(shí)現(xiàn)
        function _spread({
            for (var ar = [], i = 0; i < arguments.length; i++){
                ar = ar.concat(arguments[i]);
            }
            return ar;
        };

        用上面的例子測(cè)試一下,結(jié)果如下:

        const a1 = ['test1''test2'];
        const a2 = _spread(a1);

        a2[0] = 'test2';
        a2 // ['test2', 'test2']

        顯然,上面的例子,我們沒有考慮到屬性的可遍歷性判斷,那么需要進(jìn)一步優(yōu)化。

        嚴(yán)謹(jǐn)實(shí)現(xiàn)

        其實(shí)這里分幾種情況來考慮就好:

        1. 判斷是否為數(shù)組,數(shù)組一定可迭代,則直接復(fù)制數(shù)組后返回結(jié)果即可。
        2. 判斷是否為實(shí)現(xiàn)了遍歷器(Iterator)接口的對(duì)象,若實(shí)現(xiàn)了則轉(zhuǎn)為數(shù)組。
        3. 如果沒有實(shí)現(xiàn)遍歷器(Iterator)接口的對(duì)象,則判斷是否為普通字符串/Map/Set等。
        4. 均不滿足以上條件的話,則拋錯(cuò)。

        所以,最后實(shí)現(xiàn)為:

        function _toConsumableArray(arr{
          return (
            _arrayWithoutHoles(arr) || //  判斷是否為數(shù)組
            _iterableToArray(arr) || //  判斷是否為實(shí)現(xiàn)了遍歷器(Iterator)接口的對(duì)象
            _unsupportedIterableToArray(arr) || // 判斷是否為普調(diào)字符串/Map/Set等
            _nonIterableSpread() // 則拋錯(cuò)
          );
        }

        function _nonIterableSpread({
          throw new TypeError(
            "Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
          );
        }

        function _unsupportedIterableToArray(o, minLen{
          if (!o) return;
          if (typeof o === "string"return _arrayLikeToArray(o, minLen);
          var n = Object.prototype.toString.call(o).slice(8-1);
          if (n === "Object" && o.constructor) n = o.constructor.name;
          if (n === "Map" || n === "Set"return Array.from(o);
          if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
            return _arrayLikeToArray(o, minLen);
        }

        function _iterableToArray(iter{
          if (
            (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null) ||
            iter["@@iterator"] != null
          )
            return Array.from(iter);
        }

        function _arrayWithoutHoles(arr{
          if (Array.isArray(arr)) return _arrayLikeToArray(arr);
        }

        function _arrayLikeToArray(arr, len{
          if (len == null || len > arr.length) len = arr.length;
          for (var i = 0, arr2 = new Array(len); i < len; i++) {
            arr2[i] = arr[i];
          }
          return arr2;
        }

        更多原理探究

        我們平時(shí)在想一些 es6 的實(shí)現(xiàn)的時(shí)候,如果想知道其實(shí)現(xiàn)原理,那么可以考慮它的 es5 實(shí)現(xiàn),而如果想知道它的嚴(yán)謹(jǐn)實(shí)現(xiàn)的話??梢灾苯尤タ?babel 編譯后的 es5 代碼長什么樣即可。babel 在線編譯網(wǎng)址:https://www.babeljs.cn/repl

        如圖:




        最后


        你好,我是winty,末流本科軟件工程專業(yè)出身,目前就職于騰訊微信,掘金LV5作者。


        技術(shù)上主導(dǎo)過服務(wù)端框架設(shè)計(jì),是可視化搭建平臺(tái)的核心開發(fā),主導(dǎo)過基礎(chǔ)庫平臺(tái)搭建/前端性能sdk開發(fā)等,接觸過包括但不限于服務(wù)端、移動(dòng)端、PC端、小程序等,目前主要專注于高級(jí)前端進(jìn)階方向的學(xué)習(xí)。


        我偏愛理財(cái),喜歡折騰技術(shù);靠自己的努力已經(jīng)在廣州房車齊全,正在努力奮斗人生中的第一個(gè)千萬。上方關(guān)注后可以加我私信,點(diǎn)擊藍(lán)字查看我的奮斗之路。


        瀏覽 76
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(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>
            日韩骚女 | 精品久久精品 | 亚洲精品欧美日韩 | 欧美一级黄色小说 | 韩国三级视频在线观看 | 天天色综合天天色 | jizz99 | 张柏芝你懂的xxxxhd | 欧美性受XXX黑人XYX性爽 | 免费观看成人毛片A片入口少 |