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

          深入理解擴(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ì)象之中。

          常見(jiàn)用法

          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. 字符串/類(lèi)數(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的寫(xiě)法實(shí)現(xiàn)如下:

          // 簡(jiǎ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']

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

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

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

          1. 判斷是否為數(shù)組,數(shù)組一定可迭代,則直接復(fù)制數(shù)組后返回結(jié)果即可。
          2. 判斷是否為實(shí)現(xiàn)了遍歷器(Iterator)接口的對(duì)象,若實(shí)現(xiàn)了則轉(zhuǎn)為數(shù)組。
          3. 如果沒(méi)有實(shí)現(xiàn)遍歷器(Iterator)接口的對(duì)象,則判斷是否為普通字符串/Map/Set等。
          4. 均不滿(mǎn)足以上條件的話,則拋錯(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 代碼長(zhǎng)什么樣即可。babel 在線編譯網(wǎng)址:https://www.babeljs.cn/repl

          如圖:




          最后


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


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


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


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

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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ⅴ老师 | 亚洲欧美另类在线观看 | 天天综合网天天综合7799 | 成人国产精品秘 欧美高清 | 中文三级无码 |