10個JavaScript面試常考的前端手寫題總結(jié)
1. 實現(xiàn)一個簡單的 JavaScript 函數(shù),用于判斷一個對象是否為空
判斷對象是否為空的函數(shù) 這個函數(shù)通過遍歷對象的所有屬性來檢查是否有任何實際定義的鍵。如果在循環(huán)中找到了一個鍵,則立即返回false,表示對象不為空。如果沒有找到任何鍵,則在循環(huán)結(jié)束后返回true,表示對象為空。
function isEmptyObject(obj) { for (var key in obj) { if (obj.hasOwnProperty(key)) { return false; } } return true; }
2. 手寫數(shù)組去重
數(shù)組去重 第一個實現(xiàn)是使用傳統(tǒng)的方法,創(chuàng)建一個新的數(shù)組,并利用indexOf方法檢查當(dāng)前元素是否已存在于新數(shù)組中,不存在則添加進去。 第二個實現(xiàn)利用了ES6中的Set數(shù)據(jù)結(jié)構(gòu),它不允許重復(fù)值,所以可以直接將數(shù)組轉(zhuǎn)換為Set再轉(zhuǎn)回數(shù)組達到去重效果。
function unique(arr) { let res = []; for(let i = 0; i < arr.length; i++) { if(res.indexOf(arr[i]) === -1) { res.push(arr[i]); } } return res; } // 或者使用ES6的新特性Set function uniqueES6(arr) { return [...new Set(arr)]; }
3. 實現(xiàn)bind函數(shù)
實現(xiàn)bind函數(shù) JavaScript中原生的bind函數(shù)可以創(chuàng)建一個新的函數(shù),在調(diào)用時設(shè)置其this上下文并傳遞預(yù)設(shè)參數(shù)。這里的實現(xiàn)同樣創(chuàng)建了一個新的函數(shù),并在其內(nèi)部調(diào)用了原函數(shù),同時保證了this指向和傳參的正確性。
Function.prototype.myBind = function(context, ...args) { const self = this; return function(...newArgs) { return self.apply(context, [...args, ...newArgs]); }; };
4. 實現(xiàn)數(shù)組的map方法
實現(xiàn)map方法 Array.prototype.map() 方法創(chuàng)建一個新數(shù)組,其結(jié)果是該數(shù)組中的每個元素都調(diào)用一個提供的函數(shù)后返回的結(jié)果。這里我們模擬了這個行為,對原數(shù)組進行遍歷,并將回調(diào)函數(shù)應(yīng)用于每個元素,然后將結(jié)果推入新數(shù)組。
Array.prototype.myMap = function(callback, thisArg) { const newArray = []; for (let i = 0; i < this.length; i++) { newArray.push(callback.call(thisArg, this[i], i, this)); } return newArray; };
5. 實現(xiàn)簡易版的深拷貝
簡易版深拷貝 實現(xiàn)了一個遞歸函數(shù),用于復(fù)制給定對象的所有屬性和嵌套對象。當(dāng)遇到非對象或null類型的值時直接返回,否則創(chuàng)建一個新的對象并遞歸地復(fù)制原對象的所有屬性。
function deepClone(obj) { if (typeof obj !== 'object' || obj === null) { return obj; } let cloneObj = Array.isArray(obj) ? [] : {}; for(let key in obj) { if (obj.hasOwnProperty(key)) { cloneObj[key] = deepClone(obj[key]); } } return cloneObj; }
6. 實現(xiàn)防抖函數(shù)(debounce)
防抖函數(shù)(debounce) 防抖函數(shù)用于限制某個函數(shù)在一定時間內(nèi)只能執(zhí)行一次。例如在窗口 resize 或輸入框連續(xù)輸入事件中,防止短時間內(nèi)多次觸發(fā)。這里的實現(xiàn)是在每次調(diào)用時清除上一次的延時任務(wù),然后重新設(shè)置一個延時任務(wù),只有在指定時間間隔內(nèi)沒有再次調(diào)用時,才會執(zhí)行原函數(shù)。
function debounce(func, wait) { let timeout; return function(...args) { clearTimeout(timeout); timeout = setTimeout(() => { func.apply(this, args); }, wait); }; }
7. 實現(xiàn)節(jié)流函數(shù)(throttle)
節(jié)流函數(shù)(throttle) 節(jié)流函數(shù)確保在一定時間內(nèi),只允許函數(shù)執(zhí)行一次。與防抖不同的是,節(jié)流保證了在持續(xù)觸發(fā)的情況下,至少每隔一定時間會執(zhí)行一次函數(shù)。這里的實現(xiàn)是在觸發(fā)函數(shù)時記錄上一次執(zhí)行的時間,如果當(dāng)前時間與上次執(zhí)行時間差大于設(shè)定的時間間隔,則執(zhí)行函數(shù)
function throttle(func, delay) { let prev = Date.now(); return function(...args) { const now = Date.now(); if (now - prev >= delay) { func.apply(this, args); prev = now; } }; }
8. 實現(xiàn) Promise 的 then 方法
實現(xiàn)Promise的then方法 Promise的then方法接受兩個回調(diào)函數(shù)作為參數(shù),分別處理成功和失敗的情況。這里模擬Promise的狀態(tài)機,根據(jù)Promise當(dāng)前狀態(tài)異步執(zhí)行相應(yīng)的回調(diào)函數(shù),并處理回調(diào)返回的新Promise。
MyPromise.prototype.then = function(onFulfilled, onRejected) { let self = this; return new MyPromise((resolve, reject) => { if (self.status === 'fulfilled') { setTimeout(() => { // 異步執(zhí)行 try { let x = onFulfilled(self.value); resolvePromise(x, resolve, reject); } catch(e) { reject(e); } }, 0); } else if (self.status === 'rejected') { setTimeout(() => { try { let x = onRejected(self.reason); resolvePromise(x, resolve, reject); } catch(e) { reject(e); } }, 0); } else { self.onResolvedCallbacks.push(() => { setTimeout(() => { try { let x = onFulfilled(self.value); resolvePromise(x, resolve, reject); } catch(e) { reject(e); } }, 0); }); self.onRejectedCallbacks.push(() => { setTimeout(() => { try { let x = onRejected(self.reason); resolvePromise(x, resolve, reject); } catch(e) { reject(e); } }, 0); }); } }); }; ???????function resolvePromise(value, resolve, reject) { if (value instanceof MyPromise) { value.then(resolve, reject); } else { resolve(value); } }
9. 實現(xiàn)簡易版 Ajax 請求
簡易版Ajax請求 實現(xiàn)了一個基于XMLHttpRequest的簡易Ajax請求函數(shù),返回一個Promise對象。當(dāng)請求完成且狀態(tài)碼正常時解析響應(yīng)內(nèi)容并resolve,否則reject。
function ajax(url, method, data) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open(method, url, true); xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.status >= 200 && xhr.status < 300) { resolve(JSON.parse(xhr.responseText)); } else { reject(xhr.statusText); } } }; xhr.onerror = function() { reject(xhr.statusText); }; xhr.send(JSON.stringify(data)); }); }
10. 實現(xiàn)一個簡易版的事件委托
實現(xiàn)事件委托 事件委托是一種優(yōu)化事件處理的方式,通過監(jiān)聽父級元素的事件,然后通過事件對象判斷觸發(fā)事件的具體子元素,從而減少綁定事件的數(shù)量。在這個實現(xiàn)中,當(dāng)父元素接收到事件時,會向上遍歷事件傳播鏈,查找是否匹配特定選擇器的目標(biāo)元素,如果匹配就執(zhí)行處理器函數(shù)。
function delegateEvent(element, selector, eventType, handler) { element.addEventListener(eventType, function(event) { let target = event.target; while (target && target !== this) { if (target.matches(selector)) { handler.call(target, event); break; } target = target.parentNode; } }); }
到此這篇關(guān)于10個JavaScript面試??嫉那岸耸謱戭}總結(jié)的文章就介紹到這了,更多相關(guān)JavaScript常考手寫題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js創(chuàng)建一個input數(shù)組并綁定click事件的方法
這篇文章主要介紹了js創(chuàng)建一個input數(shù)組并綁定click事件的方法,需要的朋友可以參考下2014-06-06下載站常用的點擊下載地址提示設(shè)hao123為首頁的js代碼
最近很多下載站下載文件的時候都提示設(shè)置hao123為首頁,這里我們來分享下具體的實現(xiàn)方法,需要的朋友可以參考下2013-10-10淺析javascript異步執(zhí)行函數(shù)導(dǎo)致的變量變化問題解決思路
下面小編就為大家?guī)硪黄獪\析javascript異步執(zhí)行函數(shù)導(dǎo)致的變量變化問題解決思路。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考2016-05-05Javascript獲取當(dāng)前日期的農(nóng)歷日期代碼
這篇文章主要介紹了利用Javascript獲取當(dāng)前日期的農(nóng)歷日期代碼,很實用,需要的朋友可以參考下2014-10-10