日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
32個手撕JS,徹底擺脫初級前端(面試高頻)-上篇

 關(guān)于源碼都緊遵規(guī)范,都可跑通MDN示例,其余的大多會涉及一些關(guān)于JS的應(yīng)用題和本人面試過程

01.數(shù)組扁平化
數(shù)組扁平化是指將一個多維數(shù)組變?yōu)橐粋€一維數(shù)組

 
 
 
 
  1. const arr = [1, [2, [3, [4, 5]]], 6];
  2. // => [1, 2, 3, 4, 5, 6]
  3. 復(fù)制代碼

方法一:使用flat()

 
 
 
 
  1. const res1 = arr.flat(Infinity);
  2. 復(fù)制代碼

方法二:利用正則

 
 
 
 
  1. const res2 = JSON.stringify(arr).replace(/\[|\]/g, '').split(',');
  2. 復(fù)制代碼

但數(shù)據(jù)類型都會變?yōu)樽址?/p>

方法三:正則改良版本

 
 
 
 
  1. const res3 = JSON.parse('[' + JSON.stringify(arr).replace(/\[|\]/g, '') + ']');
  2. 復(fù)制代碼

方法四:使用reduce

 
 
 
 
  1. const flatten = arr => {
  2.   return arr.reduce((pre, cur) => {
  3.     return pre.concat(Array.isArray(cur) ? flatten(cur) : cur);
  4.   }, [])
  5. }
  6. const res4 = flatten(arr);
  7. 復(fù)制代碼

方法五:函數(shù)遞歸

 
 
 
 
  1. const res5 = [];
  2. const fn = arr => {
  3.   for (let i = 0; i < arr.length; i++) {
  4.     if (Array.isArray(arr[i])) {
  5.       fn(arr[i]);
  6.     } else {
  7.       res5.push(arr[i]);
  8.     }
  9.   }
  10. }
  11. fn(arr);
  12. 復(fù)制代碼

02.數(shù)組去重

 
 
 
 
  1. const arr = [1, 1, '1', 17, true, true, false, false, 'true', 'a', {}, {}];
  2. // => [1, '1', 17, true, false, 'true', 'a', {}, {}]
  3. 復(fù)制代碼

方法一:利用Set

 
 
 
 
  1. const res1 = Array.from(new Set(arr));
  2. 復(fù)制代碼

方法二:兩層for循環(huán)+splice

 
 
 
 
  1. const unique1 = arr => {
  2.   let len = arr.length;
  3.   for (let i = 0; i < len; i++) {
  4.     for (let j = i + 1; j < len; j++) {
  5.       if (arr[i] === arr[j]) {
  6.         arr.splice(j, 1);
  7.         // 每刪除一個樹,j--保證j的值經(jīng)過自加后不變。同時,len--,減少循環(huán)次數(shù)提升性能
  8.         len--;
  9.         j--;
  10.       }
  11.     }
  12.   }
  13.   return arr;
  14. }
  15. 復(fù)制代碼

方法三:利用indexOf

 
 
 
 
  1. const unique2 = arr => {
  2.   const res = [];
  3.   for (let i = 0; i < arr.length; i++) {
  4.     if (res.indexOf(arr[i]) === -1) res.push(arr[i]);
  5.   }
  6.   return res;
  7. }
  8. 復(fù)制代碼

當然也可以用include、filter,思路大同小異。

方法四:利用include

 
 
 
 
  1. const unique3 = arr => {
  2.   const res = [];
  3.   for (let i = 0; i < arr.length; i++) {
  4.     if (!res.includes(arr[i])) res.push(arr[i]);
  5.   }
  6.   return res;
  7. }
  8. 復(fù)制代碼

方法五:利用filter

 
 
 
 
  1. const unique4 = arr => {
  2.   return arr.filter((item, index) => {
  3.     return arr.indexOf(item) === index;
  4.   });
  5. }
  6. 復(fù)制代碼

方法六:利用Map

 
 
 
 
  1. const unique5 = arr => {
  2.   const map = new Map();
  3.   const res = [];
  4.   for (let i = 0; i < arr.length; i++) {
  5.     if (!map.has(arr[i])) {
  6.       map.set(arr[i], true)
  7.       res.push(arr[i]);
  8.     }
  9.   }
  10.   return res;
  11. }
  12. 復(fù)制代碼

03.類數(shù)組轉(zhuǎn)化為數(shù)組
類數(shù)組是具有l(wèi)ength屬性,但不具有數(shù)組原型上的方法。常見的類數(shù)組有arguments、DOM操作方法返回的結(jié)果。

方法一:Array.from

 
 
 
 
  1. Array.from(document.querySelectorAll('div'))
  2. 復(fù)制代碼

方法二:Array.prototype.slice.call()

 
 
 
 
  1. Array.prototype.slice.call(document.querySelectorAll('div'))
  2. 復(fù)制代碼

方法三:擴展運算符

 
 
 
 
  1. [...document.querySelectorAll('div')]
  2. 復(fù)制代碼

方法四:利用concat

 
 
 
 
  1. Array.prototype.concat.apply([], document.querySelectorAll('div'));
  2. 復(fù)制代碼

04.Array.prototype.filter()

 
 
 
 
  1. rray.prototype.filter = function(callback, thisArg) {
  2.   if (this == undefined) {
  3.     throw new TypeError('this is null or not undefined');
  4.   }
  5.   if (typeof callback !== 'function') {
  6.     throw new TypeError(callback + 'is not a function');
  7.   }
  8.   const res = [];
  9.   // 讓O成為回調(diào)函數(shù)的對象傳遞(強制轉(zhuǎn)換對象)
  10.   const O = Object(this);
  11.   // >>>0 保證len為number,且為正整數(shù)
  12.   const len = O.length >>> 0;
  13.   for (let i = 0; i < len; i++) {
  14.     // 檢查i是否在O的屬性(會檢查原型鏈)
  15.     if (i in O) {
  16.       // 回調(diào)函數(shù)調(diào)用傳參
  17.       if (callback.call(thisArg, O[i], i, O)) {
  18.         res.push(O[i]);
  19.       }
  20.     }
  21.   }
  22.   return res;
  23. }
  24. 復(fù)制代碼

對于>>>0有疑問的:解釋>>>0的作用

05.Array.prototype.map()

 
 
 
 
  1. Array.prototype.map = function(callback, thisArg) {
  2.   if (this == undefined) {
  3.     throw new TypeError('this is null or not defined');
  4.   }
  5.   if (typeof callback !== 'function') {
  6.     throw new TypeError(callback + ' is not a function');
  7.   }
  8.   const res = [];
  9.   // 同理
  10.   const O = Object(this);
  11.   const len = O.length >>> 0;
  12.   for (let i = 0; i < len; i++) {
  13.     if (i in O) {
  14.       // 調(diào)用回調(diào)函數(shù)并傳入新數(shù)組
  15.       res[i] = callback.call(thisArg, O[i], i, this);
  16.     }
  17.   }
  18.   return res;
  19. }
  20. 復(fù)制代碼

06.Array.prototype.forEach()

forEach跟map類似,唯一不同的是forEach是沒有返回值的。

 
 
 
 
  1. Array.prototype.forEach = function(callback, thisArg) {
  2.   if (this == null) {
  3.     throw new TypeError('this is null or not defined');
  4.   }
  5.   if (typeof callback !== "function") {
  6.     throw new TypeError(callback + ' is not a function');
  7.   }
  8.   const O = Object(this);
  9.   const len = O.length >>> 0;
  10.   let k = 0;
  11.   while (k < len) {
  12.     if (k in O) {
  13.       callback.call(thisArg, O[k], k, O);
  14.     }
  15.     k++;
  16.   }
  17. }
  18. 復(fù)制代碼

07.Array.prototype.reduce()

 
 
 
 
  1. Array.prototype.reduce = function(callback, initialValue) {
  2.   if (this == undefined) {
  3.     throw new TypeError('this is null or not defined');
  4.   }
  5.   if (typeof callback !== 'function') {
  6.     throw new TypeError(callbackfn + ' is not a function');
  7.   }
  8.   const O = Object(this);
  9.   const len = this.length >>> 0;
  10.   let accumulator = initialValue;
  11.   let k = 0;
  12.   // 如果第二個參數(shù)為undefined的情況下
  13.   // 則數(shù)組的第一個有效值作為累加器的初始值
  14.   if (accumulator === undefined) {
  15.     while (k < len && !(k in O)) {
  16.       k++;
  17.     }
  18.     // 如果超出數(shù)組界限還沒有找到累加器的初始值,則TypeError
  19.     if (k >= len) {
  20.       throw new TypeError('Reduce of empty array with no initial value');
  21.     }
  22.     accumulator = O[k++];
  23.   }
  24.   while (k < len) {
  25.     if (k in O) {
  26.       accumulator = callback.call(undefined, accumulator, O[k], k, O);
  27.     }
  28.     k++;
  29.   }
  30.   return accumulator;
  31. }
  32. 復(fù)制代碼

08.Function.prototype.apply()
第一個參數(shù)是綁定的this,默認為window,第二個參數(shù)是數(shù)組或類數(shù)組

 
 
 
 
  1. Function.prototype.apply = function(context = window, args) {
  2.   if (typeof this !== 'function') {
  3.     throw new TypeError('Type Error');
  4.   }
  5.   const fn = Symbol('fn');
  6.   context[fn] = this;
  7.   const res = context[fn](...args);
  8.   delete context[fn];
  9.   return res;
  10. }
  11. 復(fù)制代碼

09.Function.prototype.call
于call唯一不同的是,call()方法接受的是一個參數(shù)列表

 
 
 
 
  1. Function.prototype.call = function(context = window, ...args) {
  2.   if (typeof this !== 'function') {
  3.     throw new TypeError('Type Error');
  4.   }
  5.   const fn = Symbol('fn');
  6.   context[fn] = this;
  7.   const res = this[fn](...args);
  8.   delete this.fn;
  9.   return res;
  10. }
  11. 復(fù)制代碼

10.Function.prototype.bind

 
 
 
 
  1. Function.prototype.bind = function(context, ...args) {
  2.   if (typeof this !== 'function') {
  3.     throw new Error("Type Error");
  4.   }
  5.   // 保存this的值
  6.   var self = this;
  7.   return function F() {
  8.     // 考慮new的情況
  9.     if(this instanceof F) {
  10.       return new self(...args, ...arguments)
  11.     }
  12.     return self.apply(context, [...args, ...arguments])
  13.   }
  14. }
  15. 復(fù)制代碼

11.debounce(防抖)
觸發(fā)高頻時間后n秒內(nèi)函數(shù)只會執(zhí)行一次,如果n秒內(nèi)高頻時間再次觸發(fā),則重新計算時間。

 
 
 
 
  1. const debounce = (fn, time) => {
  2.   let timeout = null;
  3.   return function() {
  4.     clearTimeout(timeout)
  5.     timeout = setTimeout(() => {
  6.       fn.apply(this, arguments);
  7.     }, time);
  8.   }
  9. };
  10. 復(fù)制代碼

防抖常應(yīng)用于用戶進行搜索輸入節(jié)約請求資源,window觸發(fā)resize事件時進行防抖只觸發(fā)一次。

12.throttle(節(jié)流)
高頻時間觸發(fā),但n秒內(nèi)只會執(zhí)行一次,所以節(jié)流會稀釋函數(shù)的執(zhí)行頻率。

 
 
 
 
  1. const throttle = (fn, time) => {
  2.   let flag = true;
  3.   return function() {
  4.     if (!flag) return;
  5.     flag = false;
  6.     setTimeout(() => {
  7.       fn.apply(this, arguments);
  8.       flag = true;
  9.     }, time);
  10.   }
  11. }
  12. 復(fù)制代碼

節(jié)流常應(yīng)用于鼠標不斷點擊觸發(fā)、監(jiān)聽滾動事件。

13.函數(shù)珂里化

 
 
 
 
  1. 指的是將一個接受多個參數(shù)的函數(shù) 變?yōu)?nbsp;接受一個參數(shù)返回一個函數(shù)的固定形式,這樣便于再次調(diào)用,例如f(1)(2)

經(jīng)典面試題:實現(xiàn)add(1)(2)(3)(4)=10; 、 add(1)(1,2,3)(2)=9;

 
 
 
 
  1. function add() {
  2.   const _args = [...arguments];
  3.   function fn() {
  4.     _args.push(...arguments);
  5.     return fn;
  6.   }
  7.   fn.toString = function() {
  8.     return _args.reduce((sum, cur) => sum + cur);
  9.   }
  10.   return fn;
  11. }
  12. 復(fù)制代碼

14.模擬new操作
3個步驟:

  1. 以ctor.prototype為原型創(chuàng)建一個對象。
  2. 執(zhí)行構(gòu)造函數(shù)并將this綁定到新創(chuàng)建的對象上。
  3. 判斷構(gòu)造函數(shù)執(zhí)行返回的結(jié)果是否是引用數(shù)據(jù)類型,若是則返回構(gòu)造函數(shù)執(zhí)行的結(jié)果,否則返回創(chuàng)建的對象。
 
 
 
 
  1. function newOperator(ctor, ...args) {
  2.   if (typeof ctor !== 'function') {
  3.     throw new TypeError('Type Error');
  4.   }
  5.   const obj = Object.create(ctor.prototype);
  6.   const res = ctor.apply(obj, args);
  7.   const isObject = typeof res === 'object' && res !== null;
  8.   const isFunction = typeof res === 'function';
  9.   return isObject || isFunction ? res : obj;
  10. }
  11. 復(fù)制代碼

15.instanceof
instanceof運算符用于檢測構(gòu)造函數(shù)的prototype屬性是否出現(xiàn)在某個實例對象的原型鏈上。

 
 
 
 
  1. const myInstanceof = (left, right) => {
  2.   // 基本數(shù)據(jù)類型都返回false
  3.   if (typeof left !== 'object' || left === null) return false;
  4.   let proto = Object.getPrototypeOf(left);
  5.   while (true) {
  6.     if (proto === null) return false;
  7.     if (proto === right.prototype) return true;
  8.     proto = Object.getPrototypeOf(proto);
  9.   }
  10. }
  11. 復(fù)制代碼

16.原型繼承
這里只寫寄生組合繼承了,中間還有幾個演變過來的繼承但都有一些缺陷

 
 
 
 
  1. function Parent() {
  2.   this.name = 'parent';
  3. }
  4. function Child() {
  5.   Parent.call(this);
  6.   this.type = 'children';
  7. }
  8. Child.prototype = Object.create(Parent.prototype);
  9. Child.prototype.constructor = Child;
  10. 復(fù)制代碼

網(wǎng)站題目:32個手撕JS,徹底擺脫初級前端(面試高頻)-上篇
分享鏈接:http://www.dlmjj.cn/article/cocgspo.html