一份沉甸甸的大廠面經(jīng)
關(guān)注公眾號(hào) 前端人,回復(fù)“加群”
添加無廣告優(yōu)質(zhì)學(xué)習(xí)群
js 基礎(chǔ)
手寫 reduce
Array.prototype.myReduce = function (fn,initVal) {
let result = initVal,
i = 0;
if (typeof initVal === 'undefined') {
result = this[i]
i++;
}
while(i < this.length) {
result = fn(result, this[i])
}
return result
}
手寫 Promise.all
Promise.prototype.myAll = function (promiseArray) {
return new Promise((resolve,reject) => {
if (promiseArray.length === 0) {
return resolve([])
} else {
let res = [],count=0
for (let i = 0; i < arr.length; i++) {
// 同時(shí)也能處理arr數(shù)組中非Promise對(duì)象
if (!(promiseArray[i] instanceof Promise)) {
res[i] = promiseArray[i]
if (++count === promiseArray.length)
resolve(res)
} else {
promiseArray[i].then(data => {
res[i] = data
if (++count === promiseArray.length)
resolve(res)
}, err => {
reject(err)
})
}
}
}
})
}
requestAnimationFrame
優(yōu)勢(shì):目的是為了讓各種網(wǎng)頁動(dòng)畫效果(DOM動(dòng)畫、Canvas動(dòng)畫、SVG動(dòng)畫、WebGL動(dòng)畫)能夠有一個(gè)統(tǒng)一的刷新機(jī)制,從而節(jié)省系統(tǒng)資源,提高系統(tǒng)性能,改善視覺效果。使用這個(gè)API就是告訴瀏覽器希望執(zhí)行一個(gè)動(dòng)畫,讓瀏覽器在下一個(gè)動(dòng)畫幀安排一次網(wǎng)頁重繪。
requestAnimationFrame會(huì)把每一幀中的所有DOM操作集中起來,在一次重繪或回流中完成,并且重繪或回流的時(shí)間間隔是跟隨瀏覽器的刷新頻率 在隱藏或不可見的元素中,requestAnimationFrame將不會(huì)進(jìn)行重繪或回流,這意味著更少的cpu,gpu和內(nèi)存的使用量。
promise
是異步編程的一種解決方案,解決了回調(diào)地獄的問題。
特點(diǎn):
對(duì)象的狀態(tài)狀態(tài)不受外界影響。Promise對(duì)象代表一個(gè)異步操作,有三種狀態(tài):pending、fulfilled、rejected。只有異步操作的結(jié)果可以決定當(dāng)前是哪一種狀態(tài),任何其他操作都無法改變這個(gè)狀態(tài) 一旦狀態(tài)改變,就不會(huì)再變,任何時(shí)候都可以得到這個(gè)結(jié)果
Promise也有一些缺點(diǎn)。首先,無法取消Promise,一旦新建它就會(huì)立即執(zhí)行,無法中途取消。其次,如果不設(shè)置回調(diào)函數(shù),Promise內(nèi)部拋出的錯(cuò)誤,不會(huì)反應(yīng)到外部。第三,當(dāng)處于pending狀態(tài)時(shí),無法得知目前進(jìn)展到哪一個(gè)階段(剛剛開始還是即將完成)。
async/await
async 函數(shù)就是Generator函數(shù)的語法糖。
優(yōu)點(diǎn):
內(nèi)置執(zhí)行器 更好的語義 更廣是適用性 返回值是 Promise await命令就是內(nèi)部 then 命令的語法糖
arguments 對(duì)象
arguments對(duì)象是函數(shù)中的局部變量,他擁有 lenth屬性和索引元素,但沒有數(shù)組的其他屬性
創(chuàng)建對(duì)象的7種方法
通過Object構(gòu)造函數(shù)或?qū)ο笞置媪縿?chuàng)建單個(gè)對(duì)象 工廠模式 構(gòu)造函數(shù)模式 原型模式 組合使用構(gòu)造函數(shù)模式和原型模式 動(dòng)態(tài)原型模式 Object.create()
工廠模式
function Person() {
var o = new Object();
o.name = 'hanmeimei';
o.say = function() {
alert(this.name);
}
return o;
}
var person1 = Person();
優(yōu)點(diǎn):完成了返回一個(gè)對(duì)象的要求 缺點(diǎn): 無法通過constructor識(shí)別對(duì)象,以為都是來自O(shè)bject,無法得知來自Person 每次通過Person創(chuàng)建對(duì)象的時(shí)候,所有的say方法都是一樣的,但是卻存儲(chǔ)了多次,浪費(fèi)資源
裝飾器
裝飾器是一種特殊的聲明,可附加在類、方法、訪問器、屬性、參數(shù)聲明上。
作用:它起到了以聲明式方法將元信息添加至已有代碼的作用。
函數(shù)柯里化
是把接受多個(gè)參數(shù)的函數(shù)變換成接受一個(gè)單一參數(shù)(最初函數(shù)的第一個(gè)參數(shù))的函數(shù),并且返回接受余下的參數(shù)而且返回結(jié)果的新函數(shù)的技術(shù)。
function curry(fn, args = []) {
return function () {
let rest = [...args, ...arguments]
if (rest.length < fn.length) {
return curry.call(this, fn, rest)
} else {
return fn.apply(this, rest)
}
}
}
DOM
node.nodeType 節(jié)點(diǎn)類型常量
| 常量 | 值 | 描述 |
|---|---|---|
| Node.ELEMENT_NODE | 1 | 一個(gè)元素節(jié)點(diǎn) < p>/< div> |
| Node.TEXT_NODE | 3 | Element或Attr中實(shí)際的文字 |
| Node.CDATA_SECTION_NODE | 4 | 一個(gè) CDATASection,例如 <!CDATA[[ … ]]> |
| Node.PROCESSING_INSTRUCTION_NODE | 一個(gè)用于XML文檔的 ProcessingInstruction ,例如 < ?xml-stylesheet ... ?> 聲明。 | |
| Node.COMMENT_NODE | 8 | 一個(gè) comment 節(jié)點(diǎn)。 |
| Node.DOCUMENT_NODE | 9 | 一個(gè) Document 節(jié)點(diǎn)。 |
| Node.DOCUMENT_TYPE_NODE | 10 | 描述文檔類型的DocumentType節(jié)點(diǎn)。 |
| Node.DOCUMENT_FRAGMENT_NODE | 11 | 一個(gè)DocumentFragment節(jié)點(diǎn) |
typescript
設(shè)計(jì)泛型的關(guān)鍵目的是在成員之間提供有意義的約束,這些成員可以是:
類的實(shí)例成員 類的方法 函數(shù)參數(shù) 函數(shù)返回值
Hybrid
h5 與 Native 通信方式?
jsBridge
WebViewJavaScriptBridge的基本原理簡(jiǎn)單來說就是,建立一個(gè)橋梁,然后注冊(cè)自己,調(diào)用他人 Scheme
通過與app端約定協(xié)議名稱,app端定義協(xié)議對(duì)應(yīng)的方法,web端通過 window.location = 協(xié)議名稱的方式 通信 websocket
ios 與 android 兼容性問題
line-height 顯示效果不一致問題
在部分安卓機(jī)下設(shè)置line-height與高度相等時(shí)顯示不居中
input輸入框聚焦
input 輸入框在聚焦的時(shí)候,ios有時(shí)候會(huì)出現(xiàn) outline或者陰影,安卓則顯示正常 解決方案:input:focus{outline:none} input:{-webkit-appearance: none;}
ios系統(tǒng)會(huì)將數(shù)字當(dāng)成電話號(hào)碼,導(dǎo)致變色
<meta name="format-detection" content="telephone=no"> <meta http-equiv="x-rim-auto-match" content="none">
安卓手機(jī)可以點(diǎn)擊圖片
部分的安卓手機(jī)可以點(diǎn)擊頁面的圖片,解決方案就是通過css3給img標(biāo)簽設(shè)置不可點(diǎn)擊屬性。
img{ pointer-events: none; }
weex 原理

將vue單文件打包成 js bundle 客戶端打開某一個(gè)頁面,執(zhí)行 js bundle 客戶端提供了 js的執(zhí)行引擎 用于執(zhí)行加載到的 jsbundle js執(zhí)行引擎執(zhí)行 js Bundle,生成VNode樹進(jìn)行patch,找出最小操作DOM節(jié)點(diǎn)的操作,把對(duì)DOM的操作轉(zhuǎn)變?yōu)镹ative DOM API,調(diào)用 WXBridge進(jìn)行通信 WXBridge將渲染指令分發(fā)到 Native(Android、iOS)渲染引擎,由native 渲染引擎完成最終的頁面渲染
看完上述整體流程后,可以大致理解為何WEEX可以達(dá)到媲美原生的體驗(yàn),因?yàn)槠漤撁驿秩静⒉皇窍馠5方案一樣使用瀏覽器的渲染能力,而是原生渲染,所以本質(zhì)上渲染出來的頁面就是一個(gè)native頁面。
flutter 原理
flutter 采用自繪 ui + 原生的方式,通過在不同平臺(tái)實(shí)現(xiàn)一個(gè)統(tǒng)一的接口的渲染引擎來繪制UI,而不依賴系統(tǒng)原色控件,所以可以做到不同平臺(tái)UI的一致性。注意,自繪引擎解決的是UI的跨平臺(tái)問題,如果涉及其他系統(tǒng)能力調(diào)用,依然要涉及原生開發(fā)。
優(yōu)點(diǎn):
性能高:由于自繪引擎是直接調(diào)用系統(tǒng)API來繪制UI,所以性能和原生控件接近。 靈活、組件庫易維護(hù)、UI外觀保真度和一致性高:由于UI渲染不依賴原生控件,也就不需要根據(jù)不同平臺(tái)的控件單獨(dú)維護(hù)一套組件庫,所以代碼容易維護(hù)。由于組件庫是同一套代碼、同一個(gè)渲染引擎,所以在不同平臺(tái),組件顯示外觀可以做到高保真和高一致性;另外,由于不依賴原生控件,也就不會(huì)受原生布局系統(tǒng)的限制,這樣布局系統(tǒng)會(huì)非常靈活。不足:
動(dòng)態(tài)性不足:為了保證UI繪制性能,自繪UI系統(tǒng)一般會(huì)采用AOT模式編譯其發(fā)布包,所以應(yīng)用發(fā)布后,不能像Hybrid和RN那些使用JavaScript作為開發(fā)語言的框架那樣動(dòng)態(tài)下發(fā)代碼。
瀏覽器
同源策略
同源策略是一個(gè)重要的安全策略,它用于限制一個(gè)origin 的文檔或者它加載的腳本如何能與另一個(gè)源的資源進(jìn)行交互。它能幫助組個(gè)惡意文檔,減少可能被攻擊的媒介。
同源的定義
如果兩個(gè)url的 協(xié)議,域名,端口號(hào)都相同,則兩個(gè)url同源。
源的修改
腳本可以將 document.domain 的值設(shè)置為其當(dāng)前域或其當(dāng)前域的父域。
跨源網(wǎng)絡(luò)訪問
同源策略控制不同源之間的交互,例如在使用XMLHttpRequest 或 < img> 標(biāo)簽時(shí)則會(huì)受到同源策略的約束
跨源數(shù)據(jù)存儲(chǔ)訪問
訪問存儲(chǔ)在瀏覽器中的數(shù)據(jù),如 localStorage 和 IndexedDB,是以源進(jìn)行分割。每個(gè)源都擁有自己?jiǎn)为?dú)的存儲(chǔ)空間,一個(gè)源中的 JavaScript 腳本不能對(duì)屬于其它源的數(shù)據(jù)進(jìn)行讀寫操作。如果一個(gè)頁面包含多個(gè)iframe且他們屬于同源頁面,那么他們之間是可以共享sessionStorage的。
瀏覽器存儲(chǔ)均不支持跨域
Vue
組件的 data 為何要用 function 返回一個(gè)對(duì)象
為了保證組件在復(fù)用時(shí)數(shù)據(jù)是相互隔離的,所以每個(gè)被服用的組件的 data 都是復(fù)制的一份新的對(duì)象僅供當(dāng)前組件使用,當(dāng)某一處的組件內(nèi)的data數(shù)據(jù)被改變時(shí),其他服用的
數(shù)組響應(yīng)式監(jiān)聽
在數(shù)據(jù)初始化的時(shí)候 vue會(huì)判斷屬性值是否是數(shù)組 ,如果是數(shù)組會(huì)遍歷數(shù)組的屬性循環(huán)調(diào)用 observe 將數(shù)組中的所有屬性轉(zhuǎn)換成響應(yīng)式
同時(shí),對(duì)數(shù)組的原生API做劫持,當(dāng)使用數(shù)組的原生APi修改數(shù)組時(shí)會(huì)手動(dòng)執(zhí)行dep.notify()
響應(yīng)式原理
nextTick
可以讓我們?cè)谙麓?DOM 更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào),用于獲得更新后的 DOM 同時(shí)在Vue內(nèi)部更新render時(shí)也是調(diào)用了nextTick使得多次set的觸發(fā)會(huì)再下次微任務(wù)中統(tǒng)一執(zhí)行。
provide/inject
這對(duì)選項(xiàng)需要一起使用,以允許一個(gè)祖先組件向其所有子孫后代注入一個(gè)依賴,不論組件層次有多深,并在起上下游關(guān)系成立的時(shí)間里始終生效
提示:provide 和 inject 綁定并不是可響應(yīng)的。這是刻意為之的。然而,如果你傳入了一個(gè)可監(jiān)聽的對(duì)象,那么其對(duì)象的屬性還是可響應(yīng)的。
性能
如何做首屏優(yōu)化
路由懶加載 :當(dāng)打包構(gòu)建應(yīng)用時(shí),JavaScript包會(huì)變得非常大,影響頁面加載。如果我們能把不同路由對(duì)應(yīng)的組件分割成不同的代碼塊,然后當(dāng)路由被訪問的時(shí)候才加載對(duì)應(yīng)組件,這樣就更加高效了。 框架和模塊按需引入 開啟gzip 框架和插件從cdn中引入:可以配置 webpack 的 externals
為什么 react和Vue 一定要用 vnode?
vnode 是 DOM的描述對(duì)象,操作Vnode比操作DOM更方便 直接操作DOM會(huì)頻繁的觸發(fā)瀏覽器的重排和重繪,而操作Vnode則不會(huì) 大量的重排和重繪會(huì)導(dǎo)致瀏覽器頻繁的更新DOM樹和CSSOM以及生成RENDER樹,對(duì)性能消耗很大
當(dāng)需要大量數(shù)據(jù)渲染,在交互時(shí)點(diǎn)擊其中一行需要通知所有的行,如何做性能優(yōu)化?
頁面性能監(jiān)控指標(biāo)
根據(jù)谷歌 RAIL模型分為4個(gè)部分
Response Animation Idle Load 分別代表著web應(yīng)用的生命周期的四個(gè)不同方面。最好的性能指標(biāo)是:100ms內(nèi)響應(yīng)用戶輸入;動(dòng)畫或者滾動(dòng)需在10ms內(nèi)產(chǎn)生下一幀;最大化空閑時(shí)間;頁面加載時(shí)長(zhǎng)不超過5秒。
細(xì)分一下就是
FP/FCP FMP LCP
FP/FCP
表示首次渲染、首次有內(nèi)容的渲染
網(wǎng)絡(luò)
從輸入url到頁面加載完成的過程
首先是dns查詢 假設(shè)服務(wù)端會(huì)響應(yīng)一個(gè) HTML 文件 首先瀏覽器會(huì)判斷狀態(tài)碼是什么,如果是200就繼續(xù)解析 文件解碼成功后開始渲染流程,先根據(jù)html創(chuàng)建dom,有css的話會(huì)去構(gòu)建cssom樹,如果遇到script標(biāo)簽,會(huì)判斷是否存在async 或defer ,前者會(huì)并行進(jìn)行下載并執(zhí)行js,后者會(huì)先下載文件,然后等待html解析完成后順序執(zhí)行,如果以上都沒有,就會(huì)阻塞住渲染流程直至js執(zhí)行完畢。遇到文件下載的會(huì)去下載文件 初始html被完全加載和解析后會(huì)觸發(fā) DOMContentLoaded 事件 CSSOM 樹和DOM樹構(gòu)建完成后會(huì)開始生成Render樹,這一步就是確定頁面元素的布局、樣式等等諸多方面的東西 在生成Render樹的過程中,瀏覽器就開始調(diào)用GPU繪制,合成圖層,將內(nèi)容顯示到屏幕上
https協(xié)議的過程
客戶端向服務(wù)端發(fā)起HTTPS請(qǐng)求,連接到服務(wù)器的443端口 服務(wù)器端有一個(gè)密鑰對(duì),即公鑰和私鑰,服務(wù)端保存著私鑰,公鑰可以發(fā)送給任何人。 服務(wù)器將自己的公鑰發(fā)給客戶端。 驗(yàn)證服務(wù)端發(fā)送的數(shù)字證書的合法性,驗(yàn)證通過后客戶端會(huì)生成一個(gè)隨機(jī)值,這個(gè)隨機(jī)值就是用于進(jìn)行對(duì)稱加密的密鑰,然后用用服務(wù)器的公鑰對(duì)隨機(jī)值進(jìn)行非對(duì)稱加密。這樣客戶端的密鑰就變成了密文。 客戶端再次發(fā)起http請(qǐng)求,將加密之后的客戶端密鑰發(fā)送給服務(wù)端 服務(wù)器接收到客戶端發(fā)來的密文之后,會(huì)用自己的私鑰對(duì)其進(jìn)行非對(duì)稱解密,解密之后的明文就是客戶端密鑰(隨機(jī)值),然后用隨機(jī)值對(duì)數(shù)據(jù)進(jìn)行對(duì)稱加密,這樣數(shù)據(jù)就變成了密文 然后服務(wù)器將加密后的數(shù)據(jù)發(fā)送給客戶端 客戶端收到服務(wù)器發(fā)來的密文,用客戶端密鑰對(duì)其進(jìn)行對(duì)稱解密,得到服務(wù)器發(fā)送的數(shù)據(jù)。傳輸完成
node
node異常處理方法
同步代碼中的異常使用try{}catch結(jié)構(gòu)即可捕獲處理。 process的uncaughtException事件
那異步錯(cuò)誤該怎么處理呢?首先換個(gè)思維,因?yàn)楫惓2⒉皇鞘孪葴?zhǔn)備好的,不能控制其到底在哪兒發(fā)生,所以站更高的角度,如監(jiān)聽?wèi)?yīng)用進(jìn)程的錯(cuò)誤異常,從而捕獲不能預(yù)料的錯(cuò)誤異常,保證應(yīng)用不至于奔潰掉。
process.on('uncaughtException', (e)=>{
console.error('process error is:', e.message);
});
process.on('uncaughtException')的做法,很難去保證不造成內(nèi)存的泄漏。所以當(dāng)捕獲到異常時(shí),顯式的手動(dòng)殺掉進(jìn)程,并開始重啟node進(jìn)程,即保證釋放內(nèi)存,又保證了保證服務(wù)后續(xù)正常可用。3. 使用domain模塊
Domain 模塊可分為隱式綁定和顯式綁定:隱式綁定: 把在domain上下文中定義的變量,自動(dòng)綁定到domain對(duì)象 顯式綁定: 把不是在domain上下文中定義的變量,以代碼的方式綁定到domain對(duì)象
domin明顯的優(yōu)點(diǎn),能把出問題時(shí)的一些信息傳遞給錯(cuò)誤處理函數(shù),可以做一些打點(diǎn)上報(bào)等處理工作,最起碼保證重啟后的服務(wù),程序猿們知道發(fā)生了什么,有線索可查,也可以選擇傳遞上下文進(jìn)去,做一些后續(xù)處理。比如當(dāng)服務(wù)出錯(cuò)的時(shí)候,可以把用戶請(qǐng)求棧信息傳給下游,返回告知用戶服務(wù)異常,而不是用戶一直等到請(qǐng)求自動(dòng)超時(shí)。
但是它和process.on('uncaughtException')的做法一樣,很難去保證不造成內(nèi)存的泄漏。
一種比較好的方案是,以多進(jìn)程(cluster)的模式去部署應(yīng)用,當(dāng)某一個(gè)進(jìn)程被異常捕獲后,可以做一下打點(diǎn)上報(bào)后,開始重啟釋放內(nèi)存,此時(shí)其他請(qǐng)求被接受后,其他進(jìn)程依舊可以對(duì)外提供服務(wù),當(dāng)然前提是你的應(yīng)用不能異常多的數(shù)都數(shù)不清。
將cluster和domain結(jié)合起來使用,以多進(jìn)程的方式保證服務(wù)可用,同時(shí)可以將錯(cuò)誤信息傳遞下去進(jìn)行上報(bào),并且保留錯(cuò)誤出現(xiàn)的上下文環(huán)境,給用戶返回請(qǐng)求,不讓用戶請(qǐng)求超時(shí),然后在手動(dòng)殺死異常進(jìn)程,然后重啟。
express 與 koa的區(qū)別
用法的區(qū)別
express是基于回調(diào),也是node中最常見的error-first模式 Koa使用Async/Await實(shí)現(xiàn)異步方式
中間件的區(qū)別
express 中間件是線性模型 koa 中間件是洋蔥圈模型
集成度
express自帶了Router和static中間件 Koa需要自行安裝Router和Static的中間件
數(shù)據(jù)結(jié)構(gòu)與算法
數(shù)組去重
實(shí)現(xiàn)千位加逗號(hào)
var a = 222333444.12
function addDou(num) {
var numArr = num.split('.')
num = numArr[0]
var result = ''
while(num.length>3){
result = ','+num.slice(-3)+result
num = num.slice(0,num.length-3)
}
if(num){
result = num+result
}
result = result+'.'+numArr[1]
return result
}
console.log(addDou(a.toString()))
正則版
function addDou (num) {
num = num + ''
let numArr = num.split('.')
return numArr[0].replace(/(\d)(?=(\d{3})+$)/g, '$1,')
}
字符串排列
輸入'abc'輸出['abc','acb','bac','bca','cab','cba']
思路
本文章只研究全排列的情況,比如,還是 abc 字符串,3個(gè)字符,則總共的排列組合方式應(yīng)該有 n! 種,此處的 n 為3,則計(jì)算出來應(yīng)該是6種。本文采用遞歸方式實(shí)現(xiàn),基本思路是通過雙循環(huán)來實(shí)現(xiàn)遞歸的主邏輯部分,外層循環(huán) str,內(nèi)層循環(huán) n - 1 時(shí)的返回?cái)?shù)組 preResult 部分,算法邏輯如下方流程圖。 首先,考慮遞歸如何產(chǎn)生,假如當(dāng) n = 1,即傳參 str 的長(zhǎng)度只有1時(shí),則直接返回只有 str 的數(shù)組;當(dāng) n > 1時(shí),則考慮 n 和 n - 1 方法返回?cái)?shù)組的關(guān)系。可以想到,n 時(shí)多出的一個(gè)字符,來添加到 n - 1 返回?cái)?shù)組中每個(gè)字符串的頭部。
var perm = function(s) {
var result = [];
if (s.length <= 1) {
return [s];
} else {
for (var i = 0; i < s.length; i++) {
var c = s[i];
var newStr = s.slice(0, i) + s.slice(i + 1, s.length);
var l = perm(newStr);
for (var j = 0; j < l.length; j++) {
var tmp = c + l[j];
result.push(tmp);
}
}
}
return result;
};
數(shù)組隨機(jī)排序
// 方法1
function method1(arr){
for(var i=0,len=arr.length;i<len;i++){
var a=parseInt(Math.random()*len);
var temp=arr[a];
arr[a]=arr[i];
arr[i]=temp;
}
return arr;
}
// 方法2
function method2(arr){
var newarr=[];
while(arr.length>0){
var len=parseInt(Math.random()*arr.length);
newarr.push(arr[len]);
arr.splice(len,1) //splice(index,num,x,x)函數(shù),index刪除元素的位置(必須),num刪除的個(gè)數(shù)(必須),x向數(shù)組添加的新元素(可選)。該函數(shù)返回被刪除元素組成的新數(shù)組,同時(shí)原始數(shù)組也被改變;
}
return newarr;
}
// 方法3
function method3(arr){
arr.sort(function(){
return Math.random()-0.5;
});
console.log(arr);
}
題目1
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
輸出: [1,2,4,7,5,3,6,8,9]
// 對(duì)角線遍歷
var findDiagonalOrder = function(matrix) {
// 遍歷數(shù)組,角標(biāo)之和遞增輸出
if(matrix.length === 0){
return []
}
let res = []
let r = 0
let c = 0
let col = matrix[0].length
let row = matrix.length
for (let i = 0; i < col * row; i ++) {
//偶數(shù)向上遍歷
res[i] = matrix[r][c]
if((r + c) % 2 === 0) {
if (c === col -1) { // 當(dāng)遍歷到左后一列時(shí),本次遍歷結(jié)束,下移一行為下次遍歷做準(zhǔn)備
r++
} else if (r === 0) { // 當(dāng)遍歷到第一行時(shí),本次遍歷結(jié)束,向右移動(dòng)一格為下次遍歷做準(zhǔn)備
// 往移動(dòng)一格準(zhǔn)備向下遍歷
c++
} else { // 一般向上對(duì)角線遍歷
r--
c++
}
} else { // 奇數(shù)向下遍歷
if (r === row - 1){ // 向下遍歷到最后一行時(shí)本次遍歷結(jié)束,向右移動(dòng)一格,為下一行遍歷做準(zhǔn)備
c++
} else if (c === 0) { // 當(dāng)向下遍歷到第一列時(shí)本次遍歷結(jié)束,向下移動(dòng)一行為下一行遍歷做準(zhǔn)備
r++
} else { // 一般向下對(duì)角線遍歷
r++
c--
}
}
}
return res
};
題目2
給定有序數(shù)組[1,2,3,4,6,8,9,10] 輸出連續(xù)的值 結(jié)果為 ['1-4',6,'8-10']
function merge(arr) {
let start = 0
let res = []
arr.reduce((prev,cur,index) => {
if (cur - prev !== 1) {
let v = index - start > 1 ? `${ arr[start] }-${ arr[index - 1] }` : arr[index - 1]
res.push(v)
start = index
}
return cur
},0)
// 余下的數(shù)字就都是連續(xù)的了
if (start < arr.length - 1) res.push(`${arr[start]}-${arr[arr.length -1]}`)
else if (start === arr.length -1) res.push(arr[arr.length - 1])
return res
}來源:https://mp.weixin.qq.com/s/JRv4QxgIJX9Uny8pnACgrA
回復(fù) 資料包領(lǐng)取我整理的進(jìn)階資料包回復(fù) 加群,加入前端進(jìn)階群console.log("文章點(diǎn)贊===文章點(diǎn)在看===你我都快樂"Bug離我更遠(yuǎn)了,快樂離我更近了
