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>

        開發(fā)中經(jīng)常遇到的JavaScript問題整理(超實用)

        共 24810字,需瀏覽 50分鐘

         ·

        2021-03-03 23:31


        作者 @chengyuming 

        原文地址:https://chengyuming.cn/views/basis/issue.html

              獲取一個月有多少天

        今天遇到一個需求,已知月份,得到這個月的第一天和最后一天作為查詢條件查范圍內(nèi)的數(shù)據(jù)

        new Date(year, month, date, hrs, min, sec),new Date 可以接受這些參數(shù)創(chuàng)建一個時間對象 其中當(dāng)我們把 date 設(shè)置為 0 的時候,可以直接通過 getDate() 獲取到最后一天的日期然后得到我們要的最后一天

        new Date(2019120).getDate(); // 31
        new Date(201820).getDate(); // 28
        // 根據(jù)這個我們可以得到一個方法
        function getMonthLength(month{
          const date = new Date(month);
          const year = date.getFullYear();
          // 月份是從 0 開始計算的
          const _month = date.getMonth() + 1;
          return new Date(year, _month, 0).getDate();
        }

        關(guān)于函數(shù)的 length 屬性

        360 面試過程遇到一個很有趣的問題,是關(guān)于函數(shù)的 length 屬性的,題簡寫如下

        (() => 1).length === 0// 輸出什么

        我所理解的擁有 length 的對象一般都是數(shù)組或者類數(shù)組對象,或者定義了 length 屬性的對象,所以我回答說這個應(yīng)該是 false 吧,后來面試告訴我函數(shù)是有 length 屬性的,函數(shù)的 length 屬性就是函數(shù)參數(shù)的個數(shù),瞬間我恍然大悟,函數(shù)的參數(shù)就是 arguments,而 arguments 也是一個類數(shù)組對象所以他是有 length 屬性的

        // so
        (() => 1).length === 0// 輸出 true
        (a => a).length; // 輸出 1

        數(shù)組中字符串鍵值的處理

        在 JavaScript 中數(shù)組是通過數(shù)字進(jìn)行索引,但是有趣的是他們也是對象,所以也可以包含 字符串 鍵值和屬性,但是這些不會被計算在數(shù)組的長度(length)內(nèi)

        如果字符串鍵值能夠被強制類型轉(zhuǎn)換為十進(jìn)制數(shù)字的話,它就會被當(dāng)做數(shù)字索引來處理

        const arr = [];
        arr[0] = 1;
        arr['1'] = '嘿嘿';
        arr['cym'] = 'cym';
        console.log(arr); // [1, '嘿嘿', cym: 'cym']
        console.log(arr.length); // 2

        void 運算符

        undefined 是一個內(nèi)置標(biāo)志符,它的值為 undefined(除非被重新定義過),通過 void 運算符即可得到該值

        void 之后的語句或表達(dá)式都將返回 undefinedvoid 并不會改變表達(dá)式的結(jié)果,只是讓表達(dá)式不返回值

        void true// undefined
        void 0// undefined

        void 運算符在其他地方也可以派上用場,比如不讓表達(dá)式返回任何結(jié)果。

        // 該函數(shù)不需要有任何返回結(jié)果
        function doSomething(sign{
          if (!sign) {
            return void setTimeout(doSomething, 100);
          }
        }
        // 或許你經(jīng)常向下面一樣這么寫
        function doSomething(sign{
          if (!sign) {
            setTimeout(doSomething, 100);
            return;
          }
        }

        關(guān)于 JSON.stringify

        JSON.stringifytoString() 效果基本相同,只不過序列化的結(jié)果總是字符串

        JSON.stringify(42); // "42"
        JSON.stringify('42'); // ""42""(含有雙引號的字符串)
        JSON.stringify(null); // "null"
        JSON.stringify(true); // "true"

        不安全的 JSON 值

        所有安全的 JSON 值都可以使用 JSON.stringify 序列化,不安全的 JSON 值有:undefined、function、symbol循環(huán)引用JSON.stringify

        在對象中遇到這些不安全的 JSON 值的時候會自動將其忽略,在數(shù)組中遇到則會返回 null,以保證數(shù)組成員位置不變

        JSON.stringify(undefined); // null
        JSON.stringify(function ({}); // null
        JSON.stringify([1undefined2function ({}, 3]); // "1, null, 2, null, 3"
        JSON.stringify({ a2bfunction ({} }); // "{"a":2}"

        toJSON 方法

        如果對象中定義了 toJSON 方法,那么在 JSON 序列化的時候優(yōu)先調(diào)用該方法,主要是為了處理循環(huán)引用的時候,我們讓其返回一個合理的值

        也就是說 toJSON 方法應(yīng)該返回一個能夠被字符串安全化的 JSON

        const o = {
          a'cym',
          toJSON() {
            return { c'b' };
          },
        };

        JSON.stringify(o); // {"c":"b"}

        JSON.stringify 的第二個參數(shù)

        我們可以向 JSON.stringify 中傳遞一個可選參數(shù) replacer,他可以書數(shù)組也可以書函數(shù),用來指定對象序列化的時候哪些屬性應(yīng)該被處理,哪些應(yīng)該被排除,和 toJSON 很像

        1. 當(dāng) replacer 是一個數(shù)組時,那么他必須是一個字符串?dāng)?shù)組,其中包含序列化要處理的對象的屬性名稱,除此之外的屬性就會被忽略
        const obj = {
          a42,
          b30,
          c100,
        };
        JSON.stringify(obj, ['a''c']); // {"a":42,"c":100}
        1. 當(dāng) replacer 是一個函數(shù)時,他會對對象本身調(diào)用一次,然后在對對象中的每個屬性各調(diào)用一次。每次傳遞兩個參數(shù)(對象的鍵和值)。如果要忽略某個鍵就返回 undecided,否則就返回指定的值
        const obj = {
          a42,
          b30,
          c100,
        };
        JSON.stringify(obj, (k, v) => {
          // 注意:第一次 k 是 undefined,v 是原對象
          if (k !== 'c'return v;
        }); // "{"a":42,"b":30}"

        一元運算符

        我們都知道一個字符串轉(zhuǎn)換為數(shù)字,可以使用 + "12" 轉(zhuǎn)換為數(shù)字 12,也可以使用 -,這樣的 +、- 是一元運算符,這樣將數(shù)字轉(zhuǎn)換為字符串的方法屬于顯示轉(zhuǎn)換

        - 運算符還有反轉(zhuǎn)符號位的功能,當(dāng)然不能把一元操作符連在一起寫,不然會變成 --,當(dāng)做遞減運算符號來計算了,我們可以理解為 - 運算符出在單數(shù)次數(shù)會轉(zhuǎn)符號位,出現(xiàn)雙次數(shù)會抵消反轉(zhuǎn),比如說 1 - - 1 === 2

        # 這是 js 代碼哦,不是 python
        1 + - + - + - 1   # 0
        1 - - 1           # 2
        1 - - - 1         # 0

        字位反轉(zhuǎn)操作符 ~

        ~ 返回 2 的補碼,~x 大致等同于 -(x+1)

        ~42// -(42+1) ===> -43

        -(x+1) 中唯一能夠得到 0(或者嚴(yán)格來說時候 -0)的 x 值是 -1,也就是說 ~ 和一些數(shù)字在一起會返回一個假值 0,其他情況下則返回真值

        -1 是一個 哨位值,哨位值是那些在各個類型中被賦予了特殊含義的值。在 C 語言中 -1 代表函數(shù)執(zhí)行失敗,大于等于 0 的值代表函數(shù)執(zhí)行成功

        比如在 JavaScript 中字符串的 indexOf 方法也遵循這一慣例,該方法在字符串中搜索指定的字符串,如果找到就返回該子字符串所在的位置,否則返回 -1

        ~ 的用途

        我們知道在 JavaScript 中假值有:undefined、null、false、+0、-0、NaN、'',其他都為真值,所以負(fù)數(shù)也是真值,那么我們就可以拿著 ~indexOf 一起檢結(jié)果強制類型轉(zhuǎn)換為 真/假 值

        const str = 'hello world';
        ~str.indexOf('lo'); // -4,真值
        if (~str.indexOf('lo')) {
          // true
          // 找到匹配
        }
        ~str.indexOf('ol'); // 0,假值
        !~str.indexOf('ol'); // true
        if (!~str.indexOf('ol')) {
          // true
          // 沒有找到匹配
        }

        ~ 要比 >=0== -1 更簡潔

        字位截除

        我們經(jīng)常使用 ~~ 來截取數(shù)字值的小數(shù)部分,以為這是和 Math.floor 效果是一樣的,實際上并非如此

        ~~ 中第一個 ~ 執(zhí)行 ToInt32 并反轉(zhuǎn)字位,然后第二個在進(jìn)行一次字位反轉(zhuǎn),就是將所有的字位反轉(zhuǎn)回原值,最后得到的結(jié)果仍是 ToInt32 的結(jié)果

        ~~ 只適用于 32 位的數(shù)字,更重要的是他對負(fù)數(shù)的處理與 Math.floor 不同,所以使用時要多加注意

        Math.floor(1.9); // 1
        ~~1.9// 1
        // 操作負(fù)數(shù)
        Math.floor(-1.9); // -2
        ~~-1.9// -1

        ~~x 能將值截除為一個 32 位的整數(shù),x | 0 也可以,而且看起來更簡潔哦,不過出于對運算符優(yōu)先級的考慮,我們更傾向于使用 ~~x

        ~~1.9// 1
        1.9 | 0// 1

        ~~-1.9// -1
        -1.9 | 0// -1

        給定一組 url 實現(xiàn)并發(fā)請求

        原題是這樣的:給定一組 url,利用 js 的異步實現(xiàn)并發(fā)請求,并按順序輸出結(jié)果

        Promise.all

        首先我們可以想到的是利用 Promise.all 來實現(xiàn),代碼實現(xiàn)如下

        const urls = ['./1.json''./2.json''./3.json'];
        function getData(url{
          // 返回一個 Promise 利用 Promise.all 接受
          return new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest();
            xhr.responseType = 'json';
            xhr.onreadystatechange = () => {
              if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                  resolve(xhr.response);
                }
              }
            };
            xhr.open('GET', url, true);
            xhr.send(null);
          });
        }
        function getMultiData(urls{
          // Promise.all 接受一個包含 promise 的數(shù)組,如果不是 promise 數(shù)組會被轉(zhuǎn)成 promise
          Promise.all(urls.map(url => getData(url))).then(results => {
            console.log(results);
          });
        }

        不用 Promise

        原題是不用 Promise 來實現(xiàn),我們可以寫一個方法,加個回調(diào)函數(shù),等數(shù)據(jù)全部回來之后,觸發(fā)回調(diào)函數(shù)傳入得到的數(shù)據(jù),那么數(shù)據(jù)全部回來的就是我們要考慮的核心問題,我們可以用個數(shù)組或者對象,然后判斷一下數(shù)組的 length 和傳入的 url 的長度是否一樣來做判斷

        使用對象做映射

        const urls = ['./1.json''./2.json''./3.json'];
        function getAllDate(urls, cd{
          const result = {};
          function getData(url, idx{
            const xhr = new XMLHttpRequest();
            xhr.responseType = 'json';
            xhr.onreadystatechange = () => {
              if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                  result[idx] = xhr.response;
                  // 如果兩者 length 相等說明都請求完成了
                  if (Object.keys(result).length === urls.length) {
                    // 給對象添加length屬性,方便轉(zhuǎn)換數(shù)組
                    result.length = urls.length;
                    cd && cd(Array.from(result));
                  }
                }
              }
            };
          }
          // 觸發(fā)函數(shù)執(zhí)行
          urls.forEach((url, idx) => getData(url, idx));
        }
        // 使用
        getAllDate(urls, data => {
          console.log(data);
        });

        使用數(shù)組實現(xiàn)

        和上面的基本思路差不多,不過這次換成了數(shù)組,也可以給個信號量來做判斷

        function getGroupData(urls, cb{
          const results = [];
          let count = 0;
          const getData = url => {
            const xhr = new XMLHttpRequest();
            xhr.responseType = 'json';
            xhr.onreadystatechange = _ => {
              if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                  results.push(xhr.response);
                  if (++count === urls.length) {
                    cb && cb(results);
                  }
                }
              }
            };
            xhr.open('GET', url, true);
            xhr.send(null);
          };
          urls.forEach(url => getData(url));
        }

        getGroupData(urls, data => {
          console.log(data);
        });

        類型轉(zhuǎn)換問題

        原題:如何讓 (a == 1 && a == 2 && a == 3) 的值為 true?

        這個問題考查的數(shù)據(jù)類型轉(zhuǎn)換,== 類型轉(zhuǎn)換有個基本規(guī)則

        • NaN 與任何值都不相等,包括自己本身
        • undefinednull 相等(==),其他都不等
        • 對象與字符串類型做比較,會把對象轉(zhuǎn)換成字符串然后做比較
        • 其他類型比較都要轉(zhuǎn)換成 數(shù)字 做比較

        那么這個問題我們重寫 toString 或者 valueOf 方法就可以了

        const a = {
          val1,
          toString() {
            return this.val++;
          },
        };
        if (a == 1 && a == 2 && a == 3) {
          console.log('ok');
        }

        還有一種方法實現(xiàn)

        var i = 1;
        Object.defineProperty(window'a', {
          get() {
            return i++;
          },
        });

        if (a == 1 && a == 2 && a == 3) {
          console.log('OK');
        }

        拓展一下 [] == ![] 為什么是 true

        上面隱式類型轉(zhuǎn)換規(guī)則中提到,其他類型比較都要轉(zhuǎn)換成數(shù)字做比較,這個就是對應(yīng)那條規(guī)則的

        • 首先 [].toString() 會得到一個 '' 字符串
        • ![] 得到一個布爾值 false
        • ''false 比較肯定要轉(zhuǎn)換成數(shù)字比較
        • 那么 '' 轉(zhuǎn)換則為 0false 轉(zhuǎn)換也是 0
        • 所以這道題就是 true

        1..toString 的問題

        有時候我們看到別人的代碼中會寫到數(shù)字調(diào)其他類型的方法的時候會寫成 1..toString() 這樣的寫法

        因為直接用整數(shù)型數(shù)字調(diào)方法就會報錯,但是如果是一個浮點數(shù)的話就不會報錯了

        因為可能在 . 上面存在爭議,一個數(shù)字后面加點,解釋器他不知道你這是小數(shù)還是要調(diào)取方法,所以就跑異常了

        1.toString()     // Uncaught SyntaxError: Invalid or unexpected token
        1..toString()    // '1'
        1.2.toString()   // '1.2'

        Generator

        對象增加迭代器

        類數(shù)組對象的特征:必須有長度、索引、能夠被迭代,否則這個對象不可以使用 ... 語法轉(zhuǎn)數(shù)組,我們可以使用 Array.from 轉(zhuǎn),當(dāng)然我們也可以給對象添加一個迭代器

        const obj = {
          01,
          12,
          23,
          34,
          length4,
          [Symbol.iterator]() {
            let idx = 0
            return {
              next() {
                return {
                  value: obj[idx],
                  done: idx++ >= obj.length,
                }
              }
            }
          }
        }
        // 此時對象就被添加了迭代器
        [...obj]  // 1 2 3 4
        for (const val of obj) {
          console.log(val)  // 1 2 3 4
        }

        上面的問題可以字節(jié)使用生成器來實現(xiàn),生成器返回一個迭代器,迭代器有 next 方法,調(diào)用 next 方法可以返回 value 和 done

        const obj = {
          01,
          12,
          23,
          34,
          length4,
          [Symbol.iterator]: function* ({
            let idx = 0
            while (idx !== this.length) {
              yield this[idx++]
            }
          }

        實現(xiàn)一個字符串的迭代器

        實現(xiàn)一個字符串的迭代器:傳入一組字符串并返回單個字符的范例。一旦更新的字符串,輸出也跟著替換掉舊的

        function generator(str{
          let idx = 0;
          return {
            next() {
              return {
                value: str[idx],
                done: idx++ >= str.length,
              };
            },
          };
        }
        // 測試
        const str = 'as';
        let gen = generator(str);
        console.log(gen.next());
        console.log(gen.next());
        console.log(gen.next());
        console.log(gen.next());
        gen = generator('str');
        console.log(gen.next());
        console.log(gen.next());
        console.log(gen.next());
        console.log(gen.next());
        // { value: 'a', done: false }
        // { value: 's', done: false }
        // { value: undefined, done: true }
        // { value: undefined, done: true }
        // { value: 's', done: false }
        // { value: 't', done: false }
        // { value: 'r', done: false }
        // { value: undefined, done: true }

        簡單模擬 co

        模擬一下 co 的實現(xiàn)

        首先來看一則例子

        const fs = require('fs');
        const path = require('path');
        const { promisify } = require('util');
        const readFile = promisify(fs.readFile);

        functionread({
          const name = yield readFile(path.resolve(__dirname, 'name.txt'), 'utf8');
          const age = yield readFile(path.resolve(__dirname, name), 'utf8');
          return age;
        }

        const it = read();

        let { value, done } = it.next();
        value.then(data => {
          let { value, done } = it.next(data);
          // console.log(data, '???')
          value.then(data => {
            let { value, done } = it.next(data);
            console.log(value);
          });
        });

        使用 co 庫可以很容易解決這個問題

        const co = require('co');
        // co 接受一個生成器
        co(read()).then(data => {
          console.log(data);
        });
        // 那模擬一下
        function _co(it{
          // 首先返回一個 promise
          return new Promise((resolve, reject) => {
            // 因為可以傳值的原因,不可以直接使用循環(huán)實現(xiàn),需要使用 遞歸
            function next(data{
              const { value, done } = it.next(data);
              if (done) return resolve(value);
              // 保證值是一個 promise
              Promise.resolve(value).then(data => {
                next(data);
              }, reject);
            }
            next();
          });
        }

        菲波那切數(shù)列

        • 今天新東方的面試還提到了菲波那切數(shù)列,其實這個東西蠻很有趣,簡單介紹一下
        • 1、1、2、3、5、8、13、21、34 ....
        • 這道題有個規(guī)律,第一項加上第二項永遠(yuǎn)等于第三項:1 + 1 = 2;1 + 2 = 3;2 + 3 = 5;3 + 5 = 8 ....
        • 要求是傳入第幾項,得到該值,根據(jù)這個規(guī)律來實現(xiàn)一下

        簡單寫法

        function fibonacci(n{
          // 第一項和第二項都返回1
          if (n === 1 || n === 2return 1;
          // 我們只要返回 n - 1(n的前一項)與 n - 2(n的前兩項)的和便是我們要的值
          return fibonacci(n - 1) + fibonacci(n - 2);
        }

        優(yōu)化版本

        上面的寫法,求 20 次以內(nèi)的總和運行會很快,50 次以上特別慢,100 次 以上可能就爆棧了,所以我們需要優(yōu)化寫法,緩存每次計算后的值

        function feibo(n, sum1 = 1, sum2 = 1{
          if (n === 1 || n === 2return sum2;
          return feibo(n - 1, sum2, sum1 + sum2);
        }

        這種寫法緩存了,每次計算后的值,執(zhí)行效率會很高,100 次以上也會秒返回結(jié)果,這個也叫作尾遞歸優(yōu)化

        觀察者與發(fā)布訂閱

        一直以來,我以為發(fā)布訂閱和觀察者是一個思路,一次偶然的機(jī)會我發(fā)現(xiàn)他們是兩種不同的設(shè)計思路

        雖然他們都是實現(xiàn)了對象的一種一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴它的對象都將得倒通知,然后自動更新。但是他們之間是有一定區(qū)別的。

        觀察者模式

        觀察者模式會有 觀察者被觀察者(觀察目標(biāo)) 兩個對象存在,觀察者可以有多個,觀察目標(biāo)可以添加多個觀察者,可以通知觀察者。觀察者模式是面向與目標(biāo)和觀察者編程的,耦合目標(biāo)和觀察者

        // 被觀察者
        class Subject {
          constructor() {
            this.subs = [];
          }
          add(observer) {
            this.subs.push(observer);
          }
          notify(...args) {
            this.subs.forEach(ob => ob.update(...args));
          }
        }
        // 觀察者
        class Observer {
          update(...args) {
            console.log('Observer -> update -> args', args);
          }
        }

        // 使用
        const o1 = new Observer();
        const o2 = new Observer();
        const o3 = new Observer();
        const o5 = new Observer();
        const sub = new Subject();
        // 添加觀察者
        sub.add(o1);
        sub.add(o2);
        sub.add(o3);
        // 通知觀察者
        sub.notify('嘿嘿嘿');

        發(fā)布訂閱模式

        發(fā)布訂閱模式會有一個調(diào)度中心的概念。是面向調(diào)度中心編程的,對發(fā)布者與訂閱者解耦

        class PubSub {
          constructor() {
            this.handlers = {};
          }
          subscribe(type, fn) {
            if (!this.handlers[type]) {
              this.handlers[type] = [];
            }
            this.handlers[type].push(fn);
          }
          publish(type, ...args) {
            if (!this.handlers[type]) return;
            this.handlers[type].forEach(fn => fn(...args));
          }
        }

        const ps = new PubSub();

        ps.subscribe('a'console.log);
        ps.subscribe('a'console.log);
        ps.subscribe('a'console.log);
        ps.subscribe('a'console.log);
        ps.publish('a''hello world');

        字符串轉(zhuǎn) txt 文件(blob)

        有個要求:純前端實現(xiàn),不可以使用 nodejs

        實現(xiàn)原理也很簡單,就像我們平時下載一個本地文件一樣,可以動態(tài)的創(chuàng)建一個可以下載的 a 標(biāo)簽,給它設(shè)置 download 屬性,然后把下載的內(nèi)容轉(zhuǎn) blob 創(chuàng)建下載鏈接下載即可

        具體實現(xiàn)如下:

        function exportTxt(text, filename{
          const eleLink = document.createElement('a');
          eleLink.download = filename;
          eleLink.style.display = 'none';
          // 將內(nèi)容轉(zhuǎn)為 blob
          const blob = new Blob([text]);
          eleLink.href = URL.createObjectURL(blob);
          document.body.appendChild(eleLink);
          eleLink.click();
          document.body.removeChild(eleLink);
        }

        奇偶數(shù)判斷

        可能會遇到一個做奇偶數(shù)判斷的方法吧,反正我遇到了,一句話搞定

        const isEven = num => num % 2 === 0;

        格式化金錢

        項目中我們經(jīng)常會遇到金錢格式化需求,或者說數(shù)字格式化一下,方便閱讀(數(shù)字比較大的情況下)

        比如說 999999999,直接閱讀很不直觀,格式化后 999,999,999

        通常我們會使用正則來處理

        function formatPrice(price{
          return String(price).replace(/\B(?=(\d{3})+(?!\d))/g',');
        }

        也可以不使用正則然后優(yōu)雅的處理

        function formatPrice(price{
          return String(price)
            .split('')
            .reverse()
            .reduce((prev, next, index) => {
              return (index % 3 ? next : next + ',') + prev;
            });
        }

        上面是兩種提到的比較常用的方案,但是 js 還有個比較牛逼的 API 可以直接實現(xiàn)這個需求哦,它就是 toLocaleString,我們可以直接數(shù)字調(diào)用這個方法就可以實現(xiàn),金額的格式化

        (999999999).toLocaleString(); // 999,999,999
        // 當(dāng)然還可以更秀一點
        const options = {
          style'currency',
          currency'CNY',
        };
        (123456).toLocaleString('zh-CN', options); // ¥123,456.00

        toLocaleString 可以接收兩個可選參數(shù):localesoptions,而且這個 api 在各大瀏覽器通用不存在兼容問題并且這個 api 不止存在 Number 的原型上,Array、Object、Date 原型上都有這個 api,并且格式化出來的值可以根據(jù)我們傳入的參數(shù)出現(xiàn)各種結(jié)果

        參數(shù)及用法可以參考 MDN

        深度凍結(jié)對象

        在 vue 項目開發(fā)中,有些不變的常量,我們不想 vue 為他做雙向綁定,以減少一些性能上消耗,我們可以把使用 Object.freeze 將對象凍結(jié),此時 vue 將不會對這個對象進(jìn)行凍結(jié),但是這個凍結(jié)只是凍結(jié)對象第一層,所以遇到對象層級比較深的話,我們可以寫個深度凍結(jié)的 api,來對常量對象做一些凍結(jié)優(yōu)化

        const deepFreeze = o => {
          const propNames = Object.getOwnPropertyNames(o);
          propNames.forEach(name => {
            const prop = o[name];
            if (typeof prop === 'object' && prop !== null) {
              deepFreeze(prop);
            }
          });
          return Object.freeze(o);
        };

        脫敏處理

        在一些涉及到用戶隱私情況下,可能會遇到對用戶的手機(jī)號身份證號之類的信息脫敏,但是這個脫敏數(shù)據(jù)的規(guī)則是根據(jù)用戶信息要脫敏字段動態(tài)的生成的,此時我們動態(tài)拼接正則來實現(xiàn)一個動態(tài)脫敏規(guī)則

        const encryptReg = (before = 3, after = 4) => {
          return new RegExp('(\\d{' + before + '})\\d*(\\d{' + after + '})');
        };
        // 使用:'13456789876'.replace(encryptReg(), '$1****$2') -> "134****9876"

        樹遍歷

        對于樹結(jié)構(gòu)的遍歷一般有深度優(yōu)先和廣度優(yōu)先

        廣度優(yōu)先和深度優(yōu)先的概念很簡單,區(qū)別如下:

        • 深度優(yōu)先,訪問完一顆子樹再去訪問后面的子樹,而訪問子樹的時候,先訪問根再訪問根的子樹,稱為先序遍歷;先訪問子樹再訪問根,稱為后序遍歷。
        • 廣度優(yōu)先,即訪問樹結(jié)構(gòu)的第 n+1 層前必須先訪問完第 n 層
        1. 深度優(yōu)先

        先序遍歷

        const treeForEach = (tree, func) => {
          tree.forEach(data => {
            func(data);
            data.children && treeForEach(data.children, func);
          });
        };

        后序遍歷,只需要調(diào)換一下節(jié)點遍歷和子樹遍歷的順序即可

        const treeForEach = (tree, func) => {
          tree.forEach(data => {
            data.children && treeForEach(data.children, func);
            func(data);
          });
        };
        1. 廣度優(yōu)先

        廣度優(yōu)先的思路是,維護(hù)一個隊列,隊列的初始值為樹結(jié)構(gòu)根節(jié)點組成的列表,重復(fù)執(zhí)行以下步驟直到隊列為空。取出隊列中的第一個元素,進(jìn)行訪問相關(guān)操作,然后將其后代元素(如果有)全部追加到隊列最后。

        const treeForEach = (tree, func) => {
          let node,
            list = [...tree];
          while ((node = list.shift())) {
            func(node);
            node.children && list.push(...node.children);
          }
        };

        數(shù)組分組

        開發(fā)移動端的時候,遇到一個首頁菜單改版的需求,首頁菜單根據(jù)權(quán)限控制顯隱,而菜單每頁展示八個小菜單,超過八個做 swipe 滑動切換,當(dāng)時項目用了 vant 做的 UI 框架,菜單那模塊就選擇了他的輪播插件,菜單做成了一個扁平化的 list 配置,首先根據(jù)權(quán)限過濾出所有有權(quán)限的菜單項,然后每八個一分組,處理成一個二維數(shù)據(jù)來遍歷菜單

        const arrayGroupBySize = (arr, size = 2) => {
          const result = [];
          for (let i = 0, len = arr.length; i < len; i += size) {
            result.push(arr.slice(i, i + size));
          }
          return result;
        };

        下劃線與駝峰

        做一些數(shù)據(jù)持久化的工作的時候經(jīng)常會出現(xiàn)下劃線命名和駝峰命名的轉(zhuǎn)化,因為在前端處理中規(guī)范是駝峰命名,而像 mysql 之類的規(guī)范是下劃線命名,所以在處理后返回給前端的數(shù)據(jù)需要轉(zhuǎn)換為駝峰命名,而對數(shù)據(jù)庫的讀寫需要下劃線命名

        const toHump = name => {
          return name.replace(/\_(\w)/gfunction (all, letter{
            return letter.toUpperCase();
          });
        };

        const toLine = name => {
          return name.replace(/([A-Z])/g'_$1').toLowerCase();
        };

        校驗時間格式

        業(yè)務(wù)中遇到一個校驗一下傳入時間格式是否為一個時間格式,下面的方法可以完美校驗

        const isDate = str => {
          return typeof str !== 'number' && str !== null && new Date(str) !== 'Invalid Date';
        };

        持續(xù)記錄中...

        ??愛心三連擊

        1.看到這里了就點個在看支持下吧,你的點贊在看是我創(chuàng)作的動力。

        2.關(guān)注公眾號程序員成長指北,回復(fù)「1」加入高級前端交流群!「在這里有好多 前端 開發(fā)者,會討論 前端 Node 知識,互相學(xué)習(xí)」!

        3.也可添加微信【ikoala520】,一起成長。

        “在看轉(zhuǎn)發(fā)”是最大的支持


        瀏覽 48
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報
        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>
            丁香五月婷婷啪啪啪 | 国产精品女人高潮毛片圣水 | 麻豆91在线观看 | 在线视频自拍 | 年下疯批h嗯啊巨肉在线播放 | 女人被强行糟蹋过程h电影 | 在线永久免费观看黄网站 | 91精品国产乱码 | 91久久婷婷国产麻豆精品电影 | 韩国成人网站 |