JavaScript關(guān)于數(shù)組的四道面試題

已知后端返回一個對象數(shù)組,格式類似這樣:
const arr = [ { id: 1, name: 'a', birth: 896630400000 }, { id: 2, name: 'b', birth: 725817600000 }, ..., ]
按要求寫代碼:
- 按照 name 屬性降序排序(字母順序從大到?。?/li>
- 去除 id 屬性相同的元素(如出現(xiàn)重復(fù),后出現(xiàn)的覆蓋先出現(xiàn)的,不要求保留原始順序)
- 過濾出所有的95后(birth >= 1995年1月1日)
- 如何做前端分頁
由于公司是大數(shù)據(jù)處理業(yè)務(wù),數(shù)組相關(guān)操作使用還是挺頻繁的。這是我們公司前端JS面試題中的編程題部分。雖然都是基礎(chǔ),但是答上來的似乎不多。下面我們依次分析。
- 在看答案前不自己先試試么
- 在看答案前不自己先試試么
- 在看答案前不自己先試試么
- 在看答案前不自己先試試么
- 在看答案前不自己先試試么
- 在看答案前不自己先試試么
- 在看答案前不自己先試試么
- 在看答案前不自己先試試么
- 在看答案前不自己先試試么
- 在看答案前不自己先試試么
- 在看答案前不自己先試試么
數(shù)組排序
按照 name 屬性降序排序(字母順序從大到?。?/p>
看到排序當(dāng)然可以聯(lián)想到 Array#sort 。大家都寫過 [1, 3, 2].sort((a, b) => a - b) ,但是這個數(shù)組有點特殊,它是對象數(shù)組。排序規(guī)則也有些特殊:是按照字符串排序,而且是降序排序。
考點:
Array#sort 這個這個毫無疑問。手寫排序算法的人會被一概刷掉。難點在于在 sort 的回調(diào)函數(shù)中如何比較字符串的大小。首先字符串相減是不對的,對于 'a'-'b' 這個表達式,JS 引擎會首先把字符串 'a' 和 'b' 轉(zhuǎn)換為數(shù)字,因為 JS 標(biāo)準規(guī)定只有數(shù)字才能相減。于是:
+'a' // => NaN +'b' // => NaN 'a' - 'b' = NaN - NaN = NaN
有些同學(xué)會提出挨個比較字符編碼的方法,此法雖然可行,但是你要知道字符串長度是不固定的,你必須判斷前一位相等后比下一位,于是不得不引入循環(huán)。這并不是面試官想要的答案。
雖然字符串不可相減,但是字符串卻可以用大于小于號比較大小,而且比較的方式就是字典序依次比較。
'a' < 'b' // true 'a' < 'a' // false 'aa' < 'ab' // true
使用比較運算符比較字符串的問題就是你無法一次性得到他們的準確關(guān)系。如果 a < b 返回 false ,還有兩種可能,一種是 a 等于 b,另一種是 a 大于 b。所以如果使用比較運算符,你就必須在 sort 的回調(diào)函數(shù)中判斷兩次。
arr.sort((a, b) => a.name < b.name ? 1 : a.name > b.name ? -1 : 0); // 記得是逆序
最優(yōu)方案是使用 String#localeCompare ,這個函數(shù)可以一次性返回正負零,完美適用于 Array#sort
arr.sort((a, b) => b.name.localeCompare(a.name)); // 逆序,所以 b 在 a 前面
數(shù)組去重
去除 id 屬性相同的元素(如出現(xiàn)重復(fù),后出現(xiàn)的覆蓋先出現(xiàn)的,不要求保留原始順序)
網(wǎng)上看過一些面試題的同學(xué),看到數(shù)組去重肯定馬上會聯(lián)想到 Set ,這個玩意用來做數(shù)組去重簡直是帥到?jīng)]朋友
[...new Set([1, 1, 2, 3, 3, 1])] // => [1, 2, 3]
然而這道題卻不按套路出牌:它要去重的是對象數(shù)組,不是簡單的數(shù)字數(shù)組。
遇到這道題時可以按照這樣的思路來:題目說需要按照字段 id 去重,那么 id 是必需拿出來單獨處理的。但是 id 去重卻不是去 id 本身,而是去 id 所關(guān)聯(lián)的對象,那么肯定需要一個 id 到對象的映射。想到映射這一層,那么很容易聯(lián)想到對象和 Map 。
考點:
- 對象 key 的唯一性
- Map
如果使用對象,笨一點的話可以這樣:
const map = {}; const resultArr = []; arr.forEach(x => { if (!map[x]) { map[x] = true; resultArr.push(x); } }
這種寫法不完全符合題設(shè)要求,它總會保留最先出現(xiàn)的值。如果要保留后出現(xiàn)的值,可以把數(shù)組先反轉(zhuǎn)再遍歷。
arr.concat().reverse().forEach(...) // reverse 會改變數(shù)組的值,用之前需先克隆原始數(shù)組
這里可能有同學(xué)會提到 reduceRight,這里建議如果你不能保證回調(diào)函數(shù)為純函數(shù),請不要使用 map 或 reduce。
另外一個方式是始終用后面的對象覆蓋前面的。
const map = {}; arr.forEach(x => { map[x] = x; } const resultArr = []; for (let key in map) { // 嚴謹?shù)脑?,這里要用 hasOwnProperty 去除父級對象上的 key resultArr.push(map[key]); }
分為兩步,前一步有些類似把數(shù)組轉(zhuǎn)換為對象,后一步就是取一個對象里的所有值。前者可以用 Object#assign 或 Object#fromEntries 代替,后者就是 Object#values 。所以簡潔的寫法是這樣:
Object.values(Object.assign(...arr.map(x => ({ [x.id]: x }))));
對象其實不是一個完美的解決方案,因為對象的 key 都會被強制轉(zhuǎn)換為字符串,雖然題設(shè)中的 id 都是數(shù)字類型,但是難保后面會出現(xiàn)字符串的數(shù)字。完美的解決方案是 Set 的同胞兄弟 Map
[...new Map(arr.map(x => [x.id, x])).values()] // 注意 Map#values 返回的不是數(shù)組而是一個迭代器,需要手工再轉(zhuǎn)為數(shù)組
數(shù)組過濾
過濾出所有的95后(birth >= 1995年1月1日)
考點:
此題明顯比前面兩題簡單不少,但此題卻很少有人完全答對,問題就出在日期對象的使用上
我在之前的博文 說過 Date 對象的坑:當(dāng)你使用數(shù)字年月日構(gòu)造 Date 對象時記得月份是從 0 開始的;當(dāng)你使用字符串構(gòu)造 Date 對象時請使用斜杠( / )避免出現(xiàn)時區(qū)問題。
arr.filter(x => x.birth >= new Date(1995, 0, 1);
前端分頁
如何做前端分頁
考點:
- Array#slice
- 分頁的基本概念
所謂“分頁”就是從數(shù)組中截取要顯示的部分放到頁面上顯示,截取就是 slice,但似乎好多人把 slice 和 splice 搞混。
slice 是截取數(shù)組的一部分,但不改變原數(shù)組,兩個參數(shù)都是下標(biāo)。splice 雖然也可以作為截取數(shù)組使用,但 splice 會改變原數(shù)組,而且 splice 要求的第二個參數(shù)是截取項的長度。slice 就是截取數(shù)組,而 splice 通常用作數(shù)組中部的插入刪除操作。
slice 和 s p lice,中間差了一個字母 p ,用法含義大不相同。
const from = (頁碼 - 1) * 每頁條數(shù); arr.slice(from, from + 每頁條數(shù));
完
數(shù)組對象有很多的原生方法 ,數(shù)組操作是 JS 數(shù)據(jù)操作中最常用的操作,經(jīng)常溫習(xí)一下沒錯的。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
新手怎么學(xué)JS?JavaScript基礎(chǔ)語法入門要學(xué)什么?
這篇文章主要介紹了新手怎么學(xué)JS?JavaScript基礎(chǔ)語法入門要學(xué)什么?本文給大家介紹一個大致的學(xué)習(xí)路線和方向,需要的朋友趕緊一起來看看吧2020-03-19- 這篇文章主要介紹了javascript作用域,作用域鏈,閉包的面試題,在一些前端面試中經(jīng)常會問題,今天小編特此整理分享到腳本之家平臺,需要的朋友可以參考下2020-02-21
- 這篇文章主要介紹了2020年12道高頻JavaScript手寫面試題及答案,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編2020-01-06
- 這篇文章主要介紹了11道JS選擇題(聽說第一題就難倒80%的人),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-12-18
- JS 初學(xué)者總是對this關(guān)鍵字感到困惑,因為與其他現(xiàn)代編程語言相比,JS 中的這this關(guān)鍵字有點棘手。今天小編給大家?guī)?0個比較流行的JavaScript面試題 ,感興趣的朋友一起2019-07-12
- 這篇文章主要介紹了10個JavaScript筆試題解析,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2020-06-02