精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

開發中經常遇到的JavaScript問題整理(超實用)

開發 前端
今天遇到一個需求,已知月份,得到這個月的第一天和最后一天作為查詢條件查范圍內的數據

 [[385332]]

獲取一個月有多少天

今天遇到一個需求,已知月份,得到這個月的第一天和最后一天作為查詢條件查范圍內的數據

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

 

  1. new Date(2019, 12, 0).getDate(); // 31 
  2. new Date(2018, 2, 0).getDate(); // 28 
  3. // 根據這個我們可以得到一個方法 
  4. function getMonthLength(month) { 
  5.   const date = new Date(month); 
  6.   const year = date.getFullYear(); 
  7.   // 月份是從 0 開始計算的 
  8.   const _month = date.getMonth() + 1; 
  9.   return new Date(year, _month, 0).getDate(); 

關于函數的 length 屬性

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

 

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

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

 

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

數組中字符串鍵值的處理

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

如果字符串鍵值能夠被強制類型轉換為十進制數字的話,它就會被當做數字索引來處理

 

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

void 運算符

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

在 void 之后的語句或表達式都將返回 undefined。void 并不會改變表達式的結果,只是讓表達式不返回值

 

  1. void true; // undefined 
  2. void 0; // undefined 

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

 

  1. // 該函數不需要有任何返回結果 
  2. function doSomething(sign) { 
  3.   if (!sign) { 
  4.     return void setTimeout(doSomething, 100); 
  5.   } 
  6. // 或許你經常向下面一樣這么寫 
  7. function doSomething(sign) { 
  8.   if (!sign) { 
  9.     setTimeout(doSomething, 100); 
  10.     return
  11.   } 

關于 JSON.stringify

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

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

不安全的 JSON 值

所有安全的 JSON 值都可以使用 JSON.stringify 序列化,不安全的 JSON 值有:undefined、function、symbol 和 循環引用。JSON.stringify

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

 

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

toJSON 方法

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

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

 

  1. const o = { 
  2.   a: 'cym'
  3.   toJSON() { 
  4.     return { c: 'b' }; 
  5.   }, 
  6. }; 
  7.  
  8. JSON.stringify(o); // {"c":"b"

JSON.stringify 的第二個參數

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

1.當 replacer 是一個數組時,那么他必須是一個字符串數組,其中包含序列化要處理的對象的屬性名稱,除此之外的屬性就會被忽略

 

  1. const obj = { 
  2.   a: 42, 
  3.   b: 30, 
  4.   c: 100, 
  5. }; 
  6. JSON.stringify(obj, ['a''c']); // {"a":42,"c":100} 

2.當 replacer 是一個函數時,他會對對象本身調用一次,然后在對對象中的每個屬性各調用一次。每次傳遞兩個參數(對象的鍵和值)。如果要忽略某個鍵就返回 2.undecided,否則就返回指定的值

 

  1. const obj = { 
  2.   a: 42, 
  3.   b: 30, 
  4.   c: 100, 
  5. }; 
  6. JSON.stringify(obj, (k, v) => { 
  7.   // 注意:第一次 k 是 undefined,v 是原對象 
  8.   if (k !== 'c'return v; 
  9. }); // "{"a":42,"b":30}" 

一元運算符

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

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

 

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

字位反轉操作符

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

 

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

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

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

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

~ 的用途

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

 

  1. const str = 'hello world'
  2. ~str.indexOf('lo'); // -4,真值 
  3. if (~str.indexOf('lo')) { 
  4.   // true 
  5.   // 找到匹配 
  6. ~str.indexOf('ol'); // 0,假值 
  7. !~str.indexOf('ol'); // true 
  8. if (!~str.indexOf('ol')) { 
  9.   // true 
  10.   // 沒有找到匹配 

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

字位截除

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

~~ 中第一個 ~ 執行 ToInt32 并反轉字位,然后第二個在進行一次字位反轉,就是將所有的字位反轉回原值,最后得到的結果仍是 ToInt32 的結果

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

 

  1. Math.floor(1.9); // 1 
  2. ~~1.9; // 1 
  3. // 操作負數 
  4. Math.floor(-1.9); // -2 
  5. ~~-1.9; // -1 

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

 

  1. ~~1.9; // 1 
  2. 1.9 | 0; // 1 
  3.  
  4. ~~-1.9; // -1 
  5. -1.9 | 0; // -1 

給定一組 url 實現并發請求

原題是這樣的:給定一組 url,利用 js 的異步實現并發請求,并按順序輸出結果

Promise.all

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

 

  1. const urls = ['./1.json''./2.json''./3.json']; 
  2. function getData(url) { 
  3.   // 返回一個 Promise 利用 Promise.all 接受 
  4.   return new Promise((resolve, reject) => { 
  5.     const xhr = new XMLHttpRequest(); 
  6.     xhr.responseType = 'json'
  7.     xhr.onreadystatechange = () => { 
  8.       if (xhr.readyState === 4) { 
  9.         if (xhr.status === 200) { 
  10.           resolve(xhr.response); 
  11.         } 
  12.       } 
  13.     }; 
  14.     xhr.open('GET', url, true); 
  15.     xhr.send(null); 
  16.   }); 
  17. function getMultiData(urls) { 
  18.   // Promise.all 接受一個包含 promise 的數組,如果不是 promise 數組會被轉成 promise 
  19.   Promise.all(urls.map(url => getData(url))).then(results => { 
  20.     console.log(results); 
  21.   }); 

不用 Promise

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

使用對象做映射

 

  1. const urls = ['./1.json''./2.json''./3.json']; 
  2. function getAllDate(urls, cd) { 
  3.   const result = {}; 
  4.   function getData(url, idx) { 
  5.     const xhr = new XMLHttpRequest(); 
  6.     xhr.responseType = 'json'
  7.     xhr.onreadystatechange = () => { 
  8.       if (xhr.readyState === 4) { 
  9.         if (xhr.status === 200) { 
  10.           result[idx] = xhr.response; 
  11.           // 如果兩者 length 相等說明都請求完成了 
  12.           if (Object.keys(result).length === urls.length) { 
  13.             // 給對象添加length屬性,方便轉換數組 
  14.             result.length = urls.length; 
  15.             cd && cd(Array.from(result)); 
  16.           } 
  17.         } 
  18.       } 
  19.     }; 
  20.   } 
  21.   // 觸發函數執行 
  22.   urls.forEach((url, idx) => getData(url, idx)); 
  23. // 使用 
  24. getAllDate(urls, data => { 
  25.   console.log(data); 
  26. }); 

使用數組實現

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

 

  1. function getGroupData(urls, cb) { 
  2.   const results = []; 
  3.   let count = 0; 
  4.   const getData = url => { 
  5.     const xhr = new XMLHttpRequest(); 
  6.     xhr.responseType = 'json'
  7.     xhr.onreadystatechange = _ => { 
  8.       if (xhr.readyState === 4) { 
  9.         if (xhr.status === 200) { 
  10.           results.push(xhr.response); 
  11.           if (++count === urls.length) { 
  12.             cb && cb(results); 
  13.           } 
  14.         } 
  15.       } 
  16.     }; 
  17.     xhr.open('GET', url, true); 
  18.     xhr.send(null); 
  19.   }; 
  20.   urls.forEach(url => getData(url)); 
  21.  
  22. getGroupData(urls, data => { 
  23.   console.log(data); 
  24. }); 

類型轉換問題

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

這個問題考查的數據類型轉換,== 類型轉換有個基本規則

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

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

 

  1. const a = { 
  2.   val: 1, 
  3.   toString() { 
  4.     return this.val++; 
  5.   }, 
  6. }; 
  7. if (a == 1 && a == 2 && a == 3) { 
  8.   console.log('ok'); 

還有一種方法實現

 

  1. var i = 1; 
  2. Object.defineProperty(window, 'a', { 
  3.   get() { 
  4.     return i++; 
  5.   }, 
  6. }); 
  7.  
  8. if (a == 1 && a == 2 && a == 3) { 
  9.   console.log('OK'); 

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

上面隱式類型轉換規則中提到,其他類型比較都要轉換成數字做比較,這個就是對應那條規則的

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

1..toString 的問題

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

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

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

 

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

Generator

對象增加迭代器

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

 

  1. const obj = { 
  2.   0: 1, 
  3.   1: 2, 
  4.   2: 3, 
  5.   3: 4, 
  6.   length: 4, 
  7.   [Symbol.iterator]() { 
  8.     let idx = 0 
  9.     return { 
  10.       next() { 
  11.         return { 
  12.           value: obj[idx], 
  13.           done: idx++ >= obj.length, 
  14.         } 
  15.       } 
  16.     } 
  17.   } 
  18. // 此時對象就被添加了迭代器 
  19. [...obj]  // 1 2 3 4 
  20. for (const val of obj) { 
  21.   console.log(val)  // 1 2 3 4 

上面的問題可以字節使用生成器來實現,生成器返回一個迭代器,迭代器有 next 方法,調用 next 方法可以返回 value 和 done

 

  1. const obj = { 
  2.   0: 1, 
  3.   1: 2, 
  4.   2: 3, 
  5.   3: 4, 
  6.   length: 4, 
  7.   [Symbol.iterator]: function* () { 
  8.     let idx = 0 
  9.     while (idx !== this.length) { 
  10.       yield this[idx++] 
  11.     } 
  12.   } 

實現一個字符串的迭代器

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

 

  1. function generator(str) { 
  2.   let idx = 0; 
  3.   return { 
  4.     next() { 
  5.       return { 
  6.         value: str[idx], 
  7.         done: idx++ >= str.length, 
  8.       }; 
  9.     }, 
  10.   }; 
  11. // 測試 
  12. const str = 'as'
  13. let gen = generator(str); 
  14. console.log(gen.next()); 
  15. console.log(gen.next()); 
  16. console.log(gen.next()); 
  17. console.log(gen.next()); 
  18. gen = generator('str'); 
  19. console.log(gen.next()); 
  20. console.log(gen.next()); 
  21. console.log(gen.next()); 
  22. console.log(gen.next()); 
  23. // { value: 'a', done: false } 
  24. // { value: 's', done: false } 
  25. // { value: undefined, done: true } 
  26. // { value: undefined, done: true } 
  27. // { value: 's', done: false } 
  28. // { value: 't', done: false } 
  29. // { value: 'r', done: false } 
  30. // { value: undefined, done: true } 

簡單模擬 co

模擬一下 co 的實現

首先來看一則例子

 

  1. const fs = require('fs'); 
  2. const path = require('path'); 
  3. const { promisify } = require('util'); 
  4. const readFile = promisify(fs.readFile); 
  5.  
  6. functionread() { 
  7.   const name = yield readFile(path.resolve(__dirname, 'name.txt'), 'utf8'); 
  8.   const age = yield readFile(path.resolve(__dirname, name), 'utf8'); 
  9.   return age; 
  10.  
  11. const it = read(); 
  12.  
  13. let { value, done } = it.next(); 
  14. value.then(data => { 
  15.   let { value, done } = it.next(data); 
  16.   // console.log(data, '???'
  17.   value.then(data => { 
  18.     let { value, done } = it.next(data); 
  19.     console.log(value); 
  20.   }); 
  21. }); 

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

 

  1. const co = require('co'); 
  2. // co 接受一個生成器 
  3. co(read()).then(data => { 
  4.   console.log(data); 
  5. }); 
  6. // 那模擬一下 
  7. function _co(it) { 
  8.   // 首先返回一個 promise 
  9.   return new Promise((resolve, reject) => { 
  10.     // 因為可以傳值的原因,不可以直接使用循環實現,需要使用 遞歸 
  11.     function next(data) { 
  12.       const { value, done } = it.next(data); 
  13.       if (done) return resolve(value); 
  14.       // 保證值是一個 promise 
  15.       Promise.resolve(value).then(data => { 
  16.         next(data); 
  17.       }, reject); 
  18.     } 
  19.     next(); 
  20.   }); 

菲波那切數列

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

簡單寫法

 

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

優化版本

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

 

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

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

觀察者與發布訂閱

一直以來,我以為發布訂閱和觀察者是一個思路,一次偶然的機會我發現他們是兩種不同的設計思路

雖然他們都是實現了對象的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴它的對象都將得倒通知,然后自動更新。但是他們之間是有一定區別的。

觀察者模式

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

 

  1. // 被觀察者 
  2. class Subject { 
  3.   constructor() { 
  4.     this.subs = []; 
  5.   } 
  6.   add(observer) { 
  7.     this.subs.push(observer); 
  8.   } 
  9.   notify(...args) { 
  10.     this.subs.forEach(ob => ob.update(...args)); 
  11.   } 
  12. // 觀察者 
  13. class Observer { 
  14.   update(...args) { 
  15.     console.log('Observer -> update -> args', args); 
  16.   } 
  17.  
  18. // 使用 
  19. const o1 = new Observer(); 
  20. const o2 = new Observer(); 
  21. const o3 = new Observer(); 
  22. const o5 = new Observer(); 
  23. const sub = new Subject(); 
  24. // 添加觀察者 
  25. sub.add(o1); 
  26. sub.add(o2); 
  27. sub.add(o3); 
  28. // 通知觀察者 
  29. sub.notify('嘿嘿嘿'); 

發布訂閱模式

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

 

  1. class PubSub { 
  2.   constructor() { 
  3.     this.handlers = {}; 
  4.   } 
  5.   subscribe(type, fn) { 
  6.     if (!this.handlers[type]) { 
  7.       this.handlers[type] = []; 
  8.     } 
  9.     this.handlers[type].push(fn); 
  10.   } 
  11.   publish(type, ...args) { 
  12.     if (!this.handlers[type]) return
  13.     this.handlers[type].forEach(fn => fn(...args)); 
  14.   } 
  15.  
  16. const ps = new PubSub(); 
  17.  
  18. ps.subscribe('a', console.log); 
  19. ps.subscribe('a', console.log); 
  20. ps.subscribe('a', console.log); 
  21. ps.subscribe('a', console.log); 
  22. ps.publish('a''hello world'); 

字符串轉 txt 文件(blob)

有個要求:純前端實現,不可以使用 nodejs

實現原理也很簡單,就像我們平時下載一個本地文件一樣,可以動態的創建一個可以下載的 a 標簽,給它設置 download 屬性,然后把下載的內容轉 blob 創建下載鏈接下載即可

具體實現如下:

 

  1. function exportTxt(text, filename) { 
  2.   const eleLink = document.createElement('a'); 
  3.   eleLink.download = filename; 
  4.   eleLink.style.display = 'none'
  5.   // 將內容轉為 blob 
  6.   const blob = new Blob([text]); 
  7.   eleLink.href = URL.createObjectURL(blob); 
  8.   document.body.appendChild(eleLink); 
  9.   eleLink.click(); 
  10.   document.body.removeChild(eleLink); 

奇偶數判斷

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

 

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

格式化金錢

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

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

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

 

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

也可以不使用正則然后優雅的處理

 

  1. function formatPrice(price) { 
  2.   return String(price) 
  3.     .split(''
  4.     .reverse() 
  5.     .reduce((prev, nextindex) => { 
  6.       return (index % 3 ? next : next + ',') + prev; 
  7.     }); 

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

 

  1. (999999999).toLocaleString(); // 999,999,999 
  2. // 當然還可以更秀一點 
  3. const options = { 
  4.   style: 'currency'
  5.   currency: 'CNY'
  6. }; 
  7. (123456).toLocaleString('zh-CN', options); // ¥123,456.00 

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

參數及用法可以參考 MDN

深度凍結對象

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

 

  1. const deepFreeze = o => { 
  2.   const propNames = Object.getOwnPropertyNames(o); 
  3.   propNames.forEach(name => { 
  4.     const prop = o[name]; 
  5.     if (typeof prop === 'object' && prop !== null) { 
  6.       deepFreeze(prop); 
  7.     } 
  8.   }); 
  9.   return Object.freeze(o); 
  10. }; 

脫敏處理

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

 

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

樹遍歷

對于樹結構的遍歷一般有深度優先和廣度優先

廣度優先和深度優先的概念很簡單,區別如下:

  1. 深度優先,訪問完一顆子樹再去訪問后面的子樹,而訪問子樹的時候,先訪問根再訪問根的子樹,稱為先序遍歷;先訪問子樹再訪問根,稱為后序遍歷。
  2. 廣度優先,即訪問樹結構的第 n+1 層前必須先訪問完第 n 層

1.深度優先

先序遍歷

 

  1. const treeForEach = (tree, func) => { 
  2.   tree.forEach(data => { 
  3.     func(data); 
  4.     data.children && treeForEach(data.children, func); 
  5.   }); 
  6. }; 

后序遍歷,只需要調換一下節點遍歷和子樹遍歷的順序即可

 

  1. const treeForEach = (tree, func) => { 
  2.   tree.forEach(data => { 
  3.     data.children && treeForEach(data.children, func); 
  4.     func(data); 
  5.   }); 
  6. }; 

2.廣度優先

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

 

  1. const treeForEach = (tree, func) => { 
  2.   let node, 
  3.     list = [...tree]; 
  4.   while ((node = list.shift())) { 
  5.     func(node); 
  6.     node.children && list.push(...node.children); 
  7.   } 
  8. }; 

數組分組

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

 

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

下劃線與駝峰

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

 

  1. const toHump = name => { 
  2.   return name.replace(/\_(\w)/g, function (all, letter) { 
  3.     return letter.toUpperCase(); 
  4.   }); 
  5. }; 
  6.  
  7. const toLine = name => { 
  8.   return name.replace(/([A-Z])/g, '_$1').toLowerCase(); 
  9. }; 

校驗時間格式

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

 

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

持續記錄中...

責任編輯:華軒 來源: 程序員成長指北
相關推薦

2011-04-11 13:28:31

Oracle安裝

2011-04-11 13:25:59

Sybase安裝

2019-03-06 14:26:31

Javascript面試前端

2022-01-09 23:16:49

編程語言程序員

2020-11-08 16:04:03

開發工具技術

2010-06-04 19:31:25

遠程MySQL權限

2011-03-04 17:38:52

2010-04-21 08:50:08

2010-04-06 13:07:45

Oracle數據庫

2019-12-16 15:37:57

JavaScript人生第一份工作瀏覽器

2023-01-29 09:18:14

ScrollendJavaScript事件

2022-09-25 22:56:52

JavaScrip編程技巧

2022-09-30 09:26:35

JavaScript技巧

2010-03-31 17:17:32

2009-11-30 15:21:52

2020-07-22 13:50:39

shell命令前端

2010-04-07 16:41:50

Oracle SQL優

2010-03-22 15:38:46

Python常用模塊

2010-04-23 10:30:17

Oracle移植

2010-08-17 13:47:09

DB2還原
點贊
收藏

51CTO技術棧公眾號

涩涩涩久久久成人精品| 精品视频一二区| 激情综合亚洲| 亚洲欧美制服综合另类| 午夜免费高清视频| av激情在线| 91美女视频网站| 成人国产精品久久久| 黄色小视频在线免费看| 欧美禁忌电影| 日韩欧美美女一区二区三区| 成人观看免费完整观看| 欧美被日视频| 97精品国产露脸对白| 国产精品偷伦免费视频观看的| 国产av无码专区亚洲av毛网站| 国产乱人伦丫前精品视频| 欧美视频免费看| 亚洲视频在线播放免费| 免费av网站在线播放| 久久婷婷久久| 欧美激情va永久在线播放| b站大片免费直播| eeuss鲁片一区二区三区| 欧美亚洲自拍偷拍| 噜噜噜久久亚洲精品国产品麻豆| 麻豆视频在线播放| 久久久精品蜜桃| 国产厕所精品在线观看| 亚洲在线免费观看视频| 久久福利毛片| 国模吧一区二区| 国产一二三区精品| 波多野结衣的一区二区三区| 亚洲国产精品久久久久秋霞蜜臀| 成人亚洲免费视频| 香蕉成人影院| 日韩欧美中文字幕在线播放| 国产精品国产三级国产专区51| h视频在线观看免费| 91在线视频观看| 91视频99| www.成人免费视频| 国内外成人在线| 国产精品日日摸夜夜添夜夜av| 91video| 亚洲午夜精品久久久久久app| 精品国产一区二区三区久久狼5月 精品国产一区二区三区久久久狼 精品国产一区二区三区久久久 | 日韩字幕在线观看| 香蕉综合视频| 久久久91精品| 精品人妻伦九区久久aaa片| 日韩av久操| 色哟哟网站入口亚洲精品| a级片在线观看| 黄色美女久久久| 精品国产麻豆免费人成网站| 娇妻高潮浓精白浆xxⅹ| 久久97久久97精品免视看秋霞| 欧美成人性福生活免费看| 能看毛片的网站| 2020国产精品极品色在线观看| 精品欧美一区二区久久| 成人区人妻精品一区二| 啪啪激情综合网| 亚洲欧美国产视频| 香蕉久久久久久久| 欧美在线国产| 97视频国产在线| 亚洲大片免费观看| 欧美aaaaaa午夜精品| 成人国产精品一区二区| 国产偷人妻精品一区二区在线| 国产一区二区三区四| 不卡一卡2卡3卡4卡精品在| 亚洲精品一区二区三区不卡| 不卡一区二区在线| 青青草国产精品| 欧美69xxxx| 亚洲国产aⅴ成人精品无吗| 国产一区二区网| 91p九色成人| 91精品国产黑色紧身裤美女| 亚洲熟女一区二区| 国产在视频线精品视频www666| 最近2019中文字幕在线高清| 欧美色图亚洲天堂| 翔田千里一区二区| 成人乱人伦精品视频在线观看| 精品人妻无码一区二区色欲产成人 | 国产在线你懂得| 亚洲免费观看高清在线观看| 9久久9毛片又大又硬又粗| 日韩护士脚交太爽了| 精品日韩欧美在线| 亚洲精品国产精品国自产网站| 66久久国产| 欧美孕妇毛茸茸xxxx| 一级久久久久久久| 91亚洲男人天堂| 一区视频二区视频| 综合久久2023| 欧美成人免费网站| 肉色超薄丝袜脚交69xx图片| 99热免费精品在线观看| 成人免费网站在线| 毛片在线播放网址| 亚洲高清三级视频| 91av视频免费观看| 最近国产精品视频| 久久久久久久久久久免费精品| 成年人视频免费| 成人免费毛片片v| 正在播放一区| 三级成人在线| 亚洲黄色在线观看| 91日韩中文字幕| 日本怡春院一区二区| 国产伦视频一区二区三区| 久cao在线| 色八戒一区二区三区| 岛国精品资源网站| 中文在线日韩| 成人妇女免费播放久久久| 国产在线观看精品一区| 欧美日韩激情网| 午夜男人的天堂| 国产综合自拍| 2019国产精品视频| 欧美jizzhd欧美| 欧美日韩精品一区视频| 一区二区三区伦理片| 亚洲欧美成人| 国产在线一区二| aa级大片免费在线观看| 欧美大片在线观看一区| 裸体武打性艳史| 激情偷乱视频一区二区三区| 一区二区三区偷拍| 四虎视频在线精品免费网址| 中文字幕精品一区二区精品| 波多野结衣高清视频| 2014亚洲片线观看视频免费| 男人日女人bb视频| 视频福利一区| 国产98色在线| 成人午夜影视| 欧美三级三级三级爽爽爽| 国产又粗又猛又爽又黄的视频四季 | 国产精品久久久久久久久免费| 免费一级在线观看| 91久久香蕉国产日韩欧美9色| 中文字幕丰满乱子伦无码专区| 亚洲免费婷婷| 日韩久久不卡| 激情欧美一区二区三区黑长吊| 日韩在线观看你懂的| 亚洲专区在线播放| 亚洲精品日日夜夜| 熟妇高潮一区二区| 亚洲欧美清纯在线制服| 欧美一区二区三区成人久久片| 手机看片久久| 中文字幕亚洲一区二区三区| 艳妇乳肉豪妇荡乳av| 亚洲人精品午夜| 日本r级电影在线观看| 欧美精品三级| 久久人人爽爽人人爽人人片av| 丝袜美腿诱惑一区二区三区| 在线免费观看羞羞视频一区二区| 中文字幕人妻一区二区三区视频 | 日韩精品高清在线观看| 九一国产在线观看| 国产欧美精品一区二区三区四区| 欧美伦理片在线看| 91精品国产自产在线观看永久∴| 444亚洲人体| 色吧亚洲日本| 日韩在线免费观看视频| 成人爽a毛片一区二区| 欧美天堂在线观看| 国产性生活大片| av电影天堂一区二区在线 | 国产精品毛片久久久久久久久久99999999| 中文字幕日韩欧美| 免费观看黄色一级视频| 欧美系列日韩一区| 欧美色图一区二区| 久久久久综合网| 人妻精品久久久久中文字幕69| 国产午夜久久| 国产四区在线观看| 日韩精品亚洲aⅴ在线影院| 国产日韩av在线播放| av资源一区| 久久久国产一区| 欧美日韩在线中文字幕| 日韩一级在线观看| 国语对白做受69按摩| 一区二区三区四区乱视频| 99久久精品免费视频| 国产v综合v亚洲欧| 日韩肉感妇bbwbbwbbw| 亚洲欧洲一区| 国产盗摄视频在线观看| 日韩高清一级| 成人在线免费观看一区| 久久不卡日韩美女| 欧洲精品在线视频| 免费看电影在线| 日韩在线视频国产| 国产在线小视频| 亚洲精品短视频| 精品国产av一区二区| 欧美亚洲尤物久久| 中文字幕第四页| 亚洲国产精品久久艾草纯爱| 91麻豆精品成人一区二区| 久久久久久久久久久久久女国产乱 | 亚洲欧美日韩成人| 内射无码专区久久亚洲| 91精品在线免费| 在线免费看av片| 欧美性欧美巨大黑白大战| 国产成人在线免费观看视频| 一区二区三区国产| 538任你躁在线精品视频网站| 国产免费观看久久| 一区二区三区四区免费| 91色|porny| 波多野结衣福利| 99视频国产精品| 偷偷色噜狠狠狠狠的777米奇| 国产精品主播直播| 香蕉网在线视频| 国产美女一区二区| japan高清日本乱xxxxx| 国产麻豆成人传媒免费观看| 激情久久综合网| 国产一区二区久久| 下面一进一出好爽视频| 国产精品一区二区在线观看不卡| 亚洲第一成肉网| 狠狠久久亚洲欧美| 一级片黄色免费| 国产精品一区在线| 久久黄色一级视频| 懂色av中文一区二区三区| 中国男女全黄大片| 成人福利电影精品一区二区在线观看| 欧美一级大片免费看| 成人午夜电影久久影院| 超碰caoprom| 99热精品一区二区| www.av欧美| 欧美激情中文字幕| 日韩成人短视频| 尤物视频一区二区| 日韩免费视频网站| 黑人巨大精品欧美一区二区| 伊人久久久久久久久久久久| 欧美在线观看18| 国产精品久久久久久免费| 欧美成人精精品一区二区频| 手机av在线免费观看| 日韩精品在线视频观看| 黄色在线观看网| 日韩色av导航| 19禁羞羞电影院在线观看| 青青草国产精品一区二区| yiren22亚洲综合| 2014亚洲精品| 久久av影视| 日本xxxxx18| 在线看片不卡| 精品欧美一区免费观看α√| 日本不卡高清视频| 手机在线观看日韩av| 久久综合资源网| 欧洲美女女同性互添| 夜夜爽夜夜爽精品视频| 人人爽人人爽人人片av| 这里只有精品99re| 色视频在线观看福利| 中文字幕最新精品| 第一中文字幕在线| 国产精品视频免费在线| 99re8这里有精品热视频8在线| 清纯唯美一区二区三区| 综合激情视频| 国产一级片黄色| 国产福利一区二区| 少妇太紧太爽又黄又硬又爽小说| 亚洲综合免费观看高清在线观看| 免费看一级视频| 日韩三级视频中文字幕| 国产福利片在线| 久久久久久中文字幕| 日韩色性视频| 欧美一级片免费观看| 国产精品va| 天天干天天玩天天操| 不卡电影免费在线播放一区| 国产探花在线视频| 一本一道久久a久久精品| 国产成人精品a视频| 尤物精品国产第一福利三区| 美女91在线| 91在线视频一区| 不卡中文字幕| 国产成人久久婷婷精品流白浆| 国产高清在线精品| 欧美一区二区三区观看| 91豆麻精品91久久久久久| 天天操天天干天天爱| 九九九久久国产免费| 丰满少妇一区| 日本一区二区三区在线视频 | 久久久久五月天| 91精品一久久香蕉国产线看观看| 免费一区二区三区在在线视频| 国产精品sm| 91蝌蚪视频在线| 中文字幕在线不卡一区二区三区| 日韩精品一区不卡| 日韩国产一区三区| heyzo高清在线| 不卡视频一区二区| 欧美激情在线| 欧美日韩一区二区区| 亚洲蜜臀av乱码久久精品蜜桃| 在线亚洲欧美日韩| 色偷偷偷亚洲综合网另类| 欧美视频精品| 在线观看国产一区| 精品一区二区综合| 婷婷激情四射网| 51久久夜色精品国产麻豆| 黄视频网站在线| 91久久久久久| 欧美在线网站| 美女流白浆视频| 亚洲成人tv网| 亚洲日本国产精品| 欧美自拍大量在线观看| 色综合综合网| 精品少妇无遮挡毛片| 日本一区二区不卡视频| 亚洲视频在线观看免费视频| 中文字幕亚洲欧美日韩2019| 日韩电影精品| 国产欧美123| aaa国产一区| 国产字幕在线观看| 亚洲香蕉成视频在线观看| 欧美大片1688网站| 在线视频福利一区| 国产成人午夜高潮毛片| 国产精品成人久久| 精品亚洲一区二区| 成人一级视频| av中文字幕av| 99re视频精品| 夜夜躁日日躁狠狠久久av| www.色综合| 大型av综合网站| aⅴ在线免费观看| 国产精品久久久久天堂| 国产偷拍一区二区| 97在线观看视频| 久久精品国产亚洲夜色av网站| 91丝袜超薄交口足| 亚洲6080在线| gogogo高清在线观看免费完整版| 亚洲资源在线看| 国产一区二区三区成人欧美日韩在线观看| 一区二区三区久久久久| 91精品欧美福利在线观看| av毛片午夜不卡高**水| 五月天婷亚洲天综合网鲁鲁鲁| 国产剧情一区二区| 日韩熟女一区二区| 久久亚洲精品一区| 亚洲人成网站77777在线观看| 中文字幕亚洲欧洲| 午夜精品福利在线| 黄色网页在线看| 久久99精品久久久久久秒播放器 | 日韩欧美另类在线| 成人va天堂| 黄色激情在线视频| 国产精品久久三区| 天堂在线中文网| 成人免费在线网址| 亚洲欧美日韩国产综合精品二区 | 91视频免费观看网站| 91麻豆精品国产91久久久 | 亚洲高清毛片| 亚洲精品自拍视频在线观看|