者: Lefex 素燕
轉(zhuǎn)發(fā)鏈接:https://mp.weixin.qq.com/s/0klnoP6M90uU1g2g433swQ
源|https://segmentfault.com/a/1190000015288700
本篇文章整理總結(jié)了一些前端面試題,涵蓋面很廣,并且面的都是知名大廠,所以這些題還是很有代表性的,都掌握以后一面基礎(chǔ)面應(yīng)該沒什么問題,二面也能應(yīng)付大半,奉上:
1. 萬能居中
1.margin: 0 auto;水平
2.text-align: center;水平
3.行高,垂直
4.表格,center,middle;水平垂直
5.display:table-cell;模擬表格,all
6.絕對(duì)定位,50%減自身寬高
7.絕對(duì)定位,上下左右全0,margin:auto
8.絕對(duì)定位加相對(duì)定位。不需要知道寬高
9.IE6,IE7:給父元素設(shè)一個(gè)font-size:高度/1.14,vertical-align:middle
2. BFC優(yōu)化
塊格式化上下文, 特性:
3. 和模型哪兩種模式?什么區(qū)別?如何設(shè)置
4. 常用清除浮動(dòng)的方法,如不清除浮動(dòng)會(huì)怎樣?
當(dāng)父元素不給高度的時(shí)候,內(nèi)部元素不浮動(dòng)時(shí)會(huì)撐開, 而浮動(dòng)的時(shí)候,父元素變成一條線, 造成塌陷.
5. 柵格化的原理
比如antd的row和col, 將一行等分為24份, col是幾就占幾份, 底層按百分比實(shí)現(xiàn); 結(jié)合媒體查詢, 可以實(shí)現(xiàn)響應(yīng)式
6. 純css實(shí)現(xiàn)三角形
// 通過設(shè)置border
.box
{
width:0px;
height:0px;
border-top:50px solid rgba(0,0,0,0);
border-right:50px solid rgba(0,0,0,0);
border-bottom:50px solid green;
border-left:50px solid rgba(0,0,0,0);
}
7. 高度不定,寬100%,內(nèi)一p高不確定,如何實(shí)現(xiàn)垂直居中?
8. 至少兩種方式實(shí)現(xiàn)自適應(yīng)搜索
9. 設(shè)置一段文字的大小為6px
10. css菊花圖
四個(gè)小圓點(diǎn)一直旋轉(zhuǎn)
// 父標(biāo)簽
animation: antRotate 1.2s infinite linear;
// 子標(biāo)簽
animation: antSpin 1s infinite linear;
@keyframe antSpin {
to {
opacity: 1
}
}
@keyframe antRotate {
to {
transform: rotate(405)
}
}
// animation-delay: 逐個(gè)延遲0.4s
11. 關(guān)于em
<p style="font-size: 20px">
123
<p style="font-size: 2em;width: 2em">456</p>
</p>
// 此時(shí)子元素的font-size為40px, 寬度為80px(還要乘以子元素font-size的系數(shù))
12. 關(guān)于vh, vw
vw:viewpoint width,視窗寬度,1vw等于視窗寬度的1%。
vh:viewpoint height,視窗高度,1vh等于視窗高度的1%。
vmin:vw和vh中較小的那個(gè)。
vmax:vw和vh中較大的那個(gè)。
13. Flex布局
14. overflow原理
15. 實(shí)現(xiàn)自適應(yīng)的正方形:
16. 標(biāo)準(zhǔn)模式和怪異模式
17. CSS3實(shí)現(xiàn)環(huán)形進(jìn)度條
兩個(gè)對(duì)半矩形遮罩, 使用rotate以及overflow: hidden進(jìn)行旋轉(zhuǎn)
18. css優(yōu)先級(jí)
選擇器的特殊性值表述為4個(gè)部分,用0,0,0,0表示。
1. ES5和ES6繼承方式區(qū)別
2. Generator了解
ES6 提供的一種異步編程解決方案, Generator 函數(shù)是一個(gè)狀態(tài)機(jī),封裝了多個(gè)內(nèi)部狀態(tài)。
// 通過設(shè)置border.box { width:0px; height:0px; border-top:50px solid rgba(0,0,0,0); border-right:50px solid rgba(0,0,0,0); border-bottom:50px solid green; border-left:50px solid rgba(0,0,0,0); }
調(diào)用后返回指向內(nèi)部狀態(tài)的指針, 調(diào)用next()才會(huì)移向下一個(gè)狀態(tài), 參數(shù):
hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }
3. 手寫Promise實(shí)現(xiàn)
var myPromise=new Promise((resolve, reject)=> {
// 需要執(zhí)行的代碼
...
if (/* 異步執(zhí)行成功 */) {
resolve(value)
} else if (/* 異步執(zhí)行失敗 */) {
reject(error)
}
})
myPromise.then((value)=> {
// 成功后調(diào)用, 使用value值
}, (error)=> {
// 失敗后調(diào)用, 獲取錯(cuò)誤信息error
})
4. Promise優(yōu)缺點(diǎn)
function promise () {
this.msg='' // 存放value和error
this.status='pending'
var that=this
var process=arguments[0]
process (function () {
that.status='fulfilled'
that.msg=arguments[0]
}, function () {
that.status='rejected'
that.msg=arguments[0]
})
return this
}
promise.prototype.then=function () {
if (this.status==='fulfilled') {
arguments[0](this.msg)
} else if (this.status==='rejected' && arguments[1]) {
arguments[1](this.msg)
}
}
5. 觀察者模式
又稱發(fā)布-訂閱模式, 舉例子說明.
實(shí)現(xiàn): 發(fā)布者管理訂閱者隊(duì)列, 并有新消息推送功能. 訂閱者僅關(guān)注更新就行
6. 手寫實(shí)現(xiàn)bind
Function.prototype.bind=function () {
// 保存原函數(shù)
var self=this
// 取出第一個(gè)參數(shù)作為上下文, 相當(dāng)于[].shift.call(arguments)
var context=Array.prototype.shift.call(arguments)
// 取剩余的參數(shù)作為arg; 因?yàn)閍rguments是偽數(shù)組, 所以要轉(zhuǎn)化為數(shù)組才能使用數(shù)組方法
var arg=Array.prototype.slice.call(arguments)
// 返回一個(gè)新函數(shù)
return function () {
// 綁定上下文并傳參
self.apply(context, Array.prototype.concat.call(arg, Array.prototype.slice.call(arguments)))
}
}
7. 手寫實(shí)現(xiàn)4種繼承
<p style="font-size: 20px"> 123 <p style="font-size: 2em;width: 2em">456</p> </p>// 此時(shí)子元素的font-size為40px, 寬度為80px(還要乘以子元素font-size的系數(shù))
8. css菊花圖
四個(gè)小圓點(diǎn)一直旋轉(zhuǎn)
// 父標(biāo)簽
animation: antRotate 1.2s infinite linear;
// 子標(biāo)簽
animation: antSpin 1s infinite linear;
@keyframe antSpin {
to {
opacity: 1
}
}
@keyframe antRotate {
to {
transform: rotate(405)
}
}
// animation-delay: 逐個(gè)延遲0.4s
9. http狀態(tài)碼
10. Object.create實(shí)現(xiàn)(原型式繼承,特點(diǎn):實(shí)例的proto指向構(gòu)造函數(shù)本身)
11. async和await:
12. 算法和數(shù)據(jù)結(jié)構(gòu):
13. 封裝JSONP
function jsonp ({url, param, callback}) {
return new Promise((resolve, reject)=> {
var script=document.createElement('script')
window.callback=function (data) {
resolve(data)
document.body.removeChild('script')
}
var param={...param, callback}
var arr=[]
for (let key in param) {
arr.push(`${key}=${param[key]}`)
}
script.src=`${url}?${arr.join('&')}`
document.body.appendChild(script)
})
}
14. 手動(dòng)實(shí)現(xiàn)map(forEach以及filter也類似)
// for循環(huán)實(shí)現(xiàn)
Array.prototype.myMap=function () {
var arr=this
var [fn, thisValue]=Array.prototype.slice.call(arguments)
var result=[]
for (var i=0; i < arr.length; i++) {
result.push(fn.call(thisValue, arr[i], i, arr))
}
return result
}
var arr0=[1, 2, 3]
console.log(arr0.myMap(v=> v + 1))
// forEach實(shí)現(xiàn)(reduce類似)
Array.prototype.myMap=function (fn, thisValue) {
var result=[]
this.forEach((v, i, arr)=> {
result.push(fn.call(thisValue, v, i, arr))
})
return result
}
var arr0=[1, 2, 3]
console.log(arr0.myMap(v=> v + 1))
15. js實(shí)現(xiàn)checkbox全選以及反選
<body>
<button id="other">反選</button>
<input type="checkbox" id="all" />全選
<input type="checkbox" class="check" />1
<input type="checkbox" class="check" />2
<input type="checkbox" class="check" />3
<script>
var checkbox=document.getElementsByClassName('check')
var checkAll=document.getElementById('all')
var checkOther=document.getElementById('other')
checkAll.onclick=function() {
var flag=true
for (var i=0; i < checkbox.length; i++) {
if (!checkbox[i].checked) flag=false
}
if (flag) {
for (var i=0; i < checkbox.length; i++) {
checkbox[i].checked=false
}
} else {
for (var i=0; i < checkbox.length; i++) {
checkbox[i].checked=true
}
}
}
checkOther.onclick=function() {
for (var i=0; i < checkbox.length; i++) {
checkbox[i].checked=!checkbox[i].checked
}
}
</script>
</body>
16. 對(duì)原型鏈的理解?prototype上都有哪些屬性
17. 為什么使用繼承
通常在一般的項(xiàng)目里不需要,因?yàn)閼?yīng)用簡(jiǎn)單,但你要用純js做一些復(fù)雜的工具或框架系統(tǒng)就要用到了,比如webgis、或者js框架如jquery、ext什么的,不然一個(gè)幾千行代碼的框架不用繼承得寫幾萬行,甚至還無法維護(hù)。
18. setTimeout時(shí)間延遲為何不準(zhǔn)
單線程, 先執(zhí)行同步主線程, 再執(zhí)行異步任務(wù)隊(duì)列
19. 事件循環(huán)述,宏任務(wù)和微任務(wù)有什么區(qū)別?
20. let const var作用域
塊級(jí)作用域, 暫時(shí)性死區(qū)
21. 節(jié)流和防抖
// 函數(shù)節(jié)流 滾動(dòng)條滾動(dòng)
var canRun=true;
document.getElementById("throttle").onscroll=function(){
if(!canRun){
// 判斷是否已空閑,如果在執(zhí)行中,則直接return
return;
}
canRun=false;
setTimeout(function(){
console.log("函數(shù)節(jié)流");
canRun=true;
}, 300);
};
// 函數(shù)防抖
var timer=false;
document.getElementById("debounce").onscroll=function(){
clearTimeout(timer); // 清除未執(zhí)行的代碼,重置回初始化狀態(tài)
timer=setTimeout(function(){
console.log("函數(shù)防抖");
}, 300);
};
22. 實(shí)現(xiàn)一個(gè)sleep函數(shù)
// 這種實(shí)現(xiàn)方式是利用一個(gè)偽死循環(huán)阻塞主線程。因?yàn)镴S是單線程的。所以通過這種方式可以實(shí)現(xiàn)真正意義上的sleep()。
function sleep(delay) {
var start=(new Date()).getTime();
while ((new Date()).getTime() - start < delay) {
continue;
}
}
function test() {
console.log('111');
sleep(2000);
console.log('222');
}
test()
23. 閉包
24. Immutable.js
Facebook出品, 倡導(dǎo)數(shù)據(jù)的不可變性, 用的最多就是List和Map.
25. js實(shí)現(xiàn)instanceof
// 檢測(cè)l的原型鏈(__proto__)上是否有r.prototype,若有返回true,否則false
function myInstanceof (l, r) {
var R=r.prototype
while (l.__proto__) {
if (l.__proto__===R) return true
}
return false
}
27. ES6的模塊引入和CommonJs區(qū)別
28. 嚴(yán)格模式
// 嚴(yán)格模式下, 隱式綁定丟失后this不會(huì)指向window, 而是指向undefined
'use strict'
var a=2
var obj={
a: 1,
b: function() {
// console.log(this.a)
console.log(this)
}
}
var c=obj.b
c() // undefined
29. fetch, axios區(qū)別
30. typescript缺點(diǎn)
31. 構(gòu)造函數(shù)實(shí)現(xiàn)原理
// 模擬構(gòu)造函數(shù)實(shí)現(xiàn)
var Book=function(name) {
this.name=name;
};
//正常用法
var java=new Book(‘Master Java’);
//使用代碼模擬,在非IE瀏覽器中測(cè)試,IE瀏覽器不支持
var python={};
python.__proto__=Book.prototype;
Book.call(python, 'Master Python');
32. for in 和 for of區(qū)別
33. JS實(shí)現(xiàn)并發(fā)控制:
使用消息隊(duì)列以及setInterval或promise進(jìn)行入隊(duì)和出隊(duì)
34. ajax和axios、fetch的區(qū)別
35. promise.finally實(shí)現(xiàn)
Promise.prototype.finally=function (callback) {
let P=this.constructor;
return this.then(
value=> P.resolve(callback()).then(()=> value),
reason=> P.resolve(callback()).then(()=> { throw reason })
);
};
1. reflow(回流)和repaint(重繪)優(yōu)化
2.一個(gè)頁面從輸入 URL 到頁面加載顯示完成,這個(gè)過程中都發(fā)生了什么?
3.localStorage 與 sessionStorage 與cookie的區(qū)別總結(jié)
4.瀏覽器如何阻止事件傳播,阻止默認(rèn)行為
5.虛擬DOM方案相對(duì)原生DOM操作有什么優(yōu)點(diǎn),實(shí)現(xiàn)上是什么原理?
虛擬DOM可提升性能, 無須整體重新渲染, 而是局部刷新.
JS對(duì)象, diff算法
6.瀏覽器事件機(jī)制中事件觸發(fā)三個(gè)階段
7.什么是跨域?為什么瀏覽器要使用同源策略?你有幾種方式可以解決跨域問題?了解預(yù)檢請(qǐng)求嗎?
8.了解瀏覽器緩存機(jī)制嗎?
9.為什么操作 DOM 慢?
DOM本身是一個(gè)js對(duì)象, 操作這個(gè)對(duì)象本身不慢, 但是操作后觸發(fā)了瀏覽器的行為, 如repaint和reflow等瀏覽器行為, 使其變慢
10.什么情況會(huì)阻塞渲染?
11.如何判斷js運(yùn)行在瀏覽器中還是node中?
判斷有無全局對(duì)象global和window
12.關(guān)于web以及瀏覽器處理預(yù)加載有哪些思考?
圖片等靜態(tài)資源在使用之前就提前請(qǐng)求
資源使用到的時(shí)候能從緩存中加載, 提升用戶體驗(yàn)
頁面展示的依賴關(guān)系維護(hù)
13.http多路復(fù)用
14. http和https:
15. CSRF和XSS區(qū)別及防御
16. cookie可設(shè)置哪些屬性?httponly?
chrome控制臺(tái)的application下可查看:
17. 登錄后,前端做了哪些工作,如何得知已登錄
18. http狀態(tài)碼
19. # Http請(qǐng)求頭緩存設(shè)置方法
Cache-control, expire, last-modify
20. 實(shí)現(xiàn)頁面回退刷新
21. 正向代理和反向代理
(1)訪問原來無法訪問的資源,如google
(2) 可以做緩存,加速訪問資源
(3)對(duì)客戶端訪問授權(quán),上網(wǎng)進(jìn)行認(rèn)證
(4)代理可以記錄用戶訪問記錄(上網(wǎng)行為管理),對(duì)外隱藏用戶信息
(1)保證內(nèi)網(wǎng)的安全,可以使用反向代理提供WAF功能,阻止web攻擊大型網(wǎng)站,通常將反向代理作為公網(wǎng)訪問地址,Web服務(wù)器是內(nèi)網(wǎng)。
(2)負(fù)載均衡,通過反向代理服務(wù)器來優(yōu)化網(wǎng)站的負(fù)載
22. 關(guān)于預(yù)檢請(qǐng)求
在非簡(jiǎn)單請(qǐng)求且跨域的情況下,瀏覽器會(huì)自動(dòng)發(fā)起options預(yù)檢請(qǐng)求。
23. 三次握手四次揮手
24. TCP和UDP協(xié)議
25. 進(jìn)程和線程的區(qū)別
1. 生命周期
2 .雙向數(shù)據(jù)綁定v-model。這個(gè)最好也是自己實(shí)現(xiàn)一下 理解更深
通過v-model
VUE實(shí)現(xiàn)雙向數(shù)據(jù)綁定的原理就是利用了 Object.defineProperty() 這個(gè)方法重新定義了對(duì)象獲取屬性值(get)和設(shè)置屬性值(set)的操作來實(shí)現(xiàn)的。
function* helloWorldGenerator() { yield 'hello'; yield 'world'; return 'ending';}var hw=helloWorldGenerator();
3.vue父子組件傳遞參數(shù)
4.vue傳遞參數(shù)方法
hw.next()// { value: 'hello', done: false }hw.next()// { value: 'world', done: false }hw.next()// { value: 'ending', done: true }hw.next()// { value: undefined, done: true }
5.vue自定義組件
可以使用獨(dú)立可復(fù)用的自定義組件來構(gòu)成大型應(yīng)用, 采用帕斯卡命名法或橫線連接, 通過以上方式進(jìn)行組件間通信. 每一個(gè)組件都是Vue實(shí)例, 可以使用生命周期鉤子.
6. vue自定義指令
7.vuex組成和原理
8.vue-router的原理,例如hashhistory和History interface這些東西要弄明白。其實(shí)看一下源碼就好了,看不懂可以直接看解析的相關(guān)技術(shù)博客。
9.vue的seo問題
seo關(guān)系到網(wǎng)站排名, vue搭建spa做前后端分離不好做seo, 可通過其他方法解決:
10.預(yù)渲染和ssr
以上
11.生命周期內(nèi)create和mounted的區(qū)別
12.監(jiān)聽watch
對(duì)應(yīng)一個(gè)對(duì)象,鍵是觀察表達(dá)式,值是對(duì)應(yīng)回調(diào)。值也可以是methods的方法名,或者是對(duì)象,包含選項(xiàng)。在實(shí)例化時(shí)為每個(gè)鍵調(diào)用 $watch()
13.登錄驗(yàn)證攔截(通過router)
var myPromise=new Promise((resolve, reject)=> { // 需要執(zhí)行的代碼 ... if (/* 異步執(zhí)行成功 */) { resolve(value) } else if (/* 異步執(zhí)行失敗 */) { reject(error) }})myPromise.then((value)=> { // 成功后調(diào)用, 使用value值}, (error)=> { // 失敗后調(diào)用, 獲取錯(cuò)誤信息error})
router.beforeEach((from, to, next)=> {
if (to.meta.requireAuth) { // 判斷跳轉(zhuǎn)的路由是否需要登錄
if (store.state.token) { // vuex.state判斷token是否存在
next() // 已登錄
} else {
next({
path: '/login',
query: {redirect: to.fullPath} // 將跳轉(zhuǎn)的路由path作為參數(shù),登錄成功后跳轉(zhuǎn)到該路由
})
}
} else {
next()
}
})
14. v-for key值
不寫key值會(huì)報(bào)warning, 和react的array渲染類似. 根據(jù)diff算法, 修改數(shù)組后, 寫key值會(huì)復(fù)用, 不寫會(huì)重新生成, 造成性能浪費(fèi)或某些不必要的錯(cuò)誤
15. vue3.0的更新和defineProperty優(yōu)化
15. vue使用this獲取變量
正常要通過vm.[圖片上傳失敗...(image-6d2f4e-1570591304185)]
root傳參取值
16. jQuery的優(yōu)缺點(diǎn),與vue的不同,vue的優(yōu)缺點(diǎn)?
17. vue解除雙向綁定
function promise () { this.msg='' // 存放value和error this.status='pending' var that=this var process=arguments[0] process (function () { that.status='fulfilled' that.msg=arguments[0] }, function () { that.status='rejected' that.msg=arguments[0] }) return this}promise.prototype.then=function () { if (this.status==='fulfilled') { arguments[0](this.msg) } else if (this.status==='rejected' && arguments[1]) { arguments[1](this.msg) }}
18. vue異步組件
為了簡(jiǎn)化,Vue 允許你以一個(gè)工廠函數(shù)的方式定義你的組件,這個(gè)工廠函數(shù)會(huì)異步解析你的組件定義。Vue 只有在這個(gè)組件需要被渲染的時(shí)候才會(huì)觸發(fā)該工廠函數(shù),且會(huì)把結(jié)果緩存起來供未來重渲染
Vue.component(
'async-webpack-example',
// 這個(gè) `import` 函數(shù)會(huì)返回一個(gè) `Promise` 對(duì)象。
()=> import('./my-async-component')
)
19. MVC與MVVM
20. vue漸進(jìn)式
小到可以只使用核心功能,比如單文件組件作為一部分嵌入;大到使用整個(gè)工程,vue init webpack my-project來構(gòu)建項(xiàng)目;VUE的核心庫及其生態(tài)系統(tǒng)也可以滿足你的各式需求(core+vuex+vue-route)
1. 新舊生命周期
2. react核心
3. fiber核心(react 16)
4. 渲染一個(gè)react
5. 高階組件
高階組件就是一個(gè)函數(shù),且該函數(shù)(wrapper)接受一個(gè)組件作為參數(shù),并返回一個(gè)新的組件。
高階組件并不關(guān)心數(shù)據(jù)使用的方式和原因,而被包裹的組件也不關(guān)心數(shù)據(jù)來自何處.
6. hook(v16.7測(cè)試)
在無狀態(tài)組件(如函數(shù)式組件)中也能操作state以及其他react特性, 通過useState
7. redux和vuex以及dva:
8. react和vue的區(qū)別
9. react單向數(shù)據(jù)流怎么理解
React是單向數(shù)據(jù)流,數(shù)據(jù)主要從父節(jié)點(diǎn)傳遞到子節(jié)點(diǎn)(通過props)。如果頂層(父級(jí))的某個(gè)props改變了,React會(huì)重渲染所有的子節(jié)點(diǎn)。
10. React算法復(fù)雜度優(yōu)化
react樹對(duì)比是按照層級(jí)去對(duì)比的, 他會(huì)給樹編號(hào)0,1,2,3,4.... 然后相同的編號(hào)進(jìn)行比較。所以復(fù)雜度是n,這個(gè)好理解。
關(guān)鍵是傳統(tǒng)diff的復(fù)雜度是怎么算的?傳統(tǒng)的diff需要出了上面的比較之外,還需要跨級(jí)比較。他會(huì)將兩個(gè)樹的節(jié)點(diǎn),兩兩比較,這就有n^2的復(fù)雜度了。然后還需要編輯樹,編輯的樹可能發(fā)生在任何節(jié)點(diǎn),需要對(duì)樹進(jìn)行再一次遍歷操作,因此復(fù)雜度為n。加起來就是n^3了。
11. React優(yōu)點(diǎn)
聲明式, 組件化, 一次學(xué)習(xí), 隨處編寫. 靈活, 豐富, 輕巧, 高效
1. 移動(dòng)端兼容適配
2. flexible如何實(shí)現(xiàn)自動(dòng)判斷dpr
判斷機(jī)型, 找出樣本機(jī)型去適配. 比如iphone以6為樣本, 寬度375px, dpr是2
3. 為什么以iPhone6為標(biāo)準(zhǔn)的設(shè)計(jì)稿的尺寸是以750px寬度來設(shè)計(jì)的呢?
iPhone6的滿屏寬度是375px,而iPhone6采用的視網(wǎng)膜屏的物理像素是滿屏寬度的2倍,也就是dpr(設(shè)備像素比)為2, 并且設(shè)計(jì)師所用的PS設(shè)計(jì)軟件分辨率和像素關(guān)系是1:1。所以為了做出的清晰的頁面,設(shè)計(jì)師一般給出750px的設(shè)計(jì)圖,我們?cè)俑鶕?jù)需求對(duì)元素的尺寸設(shè)計(jì)和壓縮。
4. 如何處理異形屏iphone X
5. 移動(dòng)端首屏優(yōu)化
6. PWA全稱Progressive Web App,即漸進(jìn)式WEB應(yīng)用
一個(gè) PWA 應(yīng)用首先是一個(gè)網(wǎng)頁, 可以通過 Web 技術(shù)編寫出一個(gè)網(wǎng)頁應(yīng)用. 隨后添加上 App Manifest 和 Service Worker 來實(shí)現(xiàn) PWA 的安裝和離線等功能
解決了哪些問題?
7. 離線包方案
現(xiàn)在 web 頁面在移動(dòng)端的地位越來越高,大部分主流 App 采用 native + webview 的 hybrid 模式,加載遠(yuǎn)程頁面受限于網(wǎng)絡(luò),本地 webview 引擎,經(jīng)常會(huì)出現(xiàn)渲染慢導(dǎo)致的白屏現(xiàn)象,體驗(yàn)很差,于是離線包方案應(yīng)運(yùn)而生。動(dòng)態(tài)下載的離線包可以使得我們不需要走完整的 App 審核發(fā)布流程就完成了版本的更新
8. 自適應(yīng)和響應(yīng)式布局的區(qū)別
1. babel和polyfill
2. jpg, jpeg和png區(qū)別
3. git rebase和merge區(qū)別
1.JSBridge通信原理, 有哪幾種實(shí)現(xiàn)的方式?
JsBridge給JavaScript提供了調(diào)用Native功能,Native也能夠操控JavaScript。這樣前端部分就可以方便使用地理位置、攝像頭以及登錄支付等Native能力啦。JSBridge構(gòu)建 Native和非Native間消息通信的通道,而且是 雙向通信的通道。
2.實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 JSBridge,設(shè)計(jì)思路?
1. 二分查找和冒泡排序
2. 快速排序
Function.prototype.bind=function () { // 保存原函數(shù) var self=this // 取出第一個(gè)參數(shù)作為上下文, 相當(dāng)于[].shift.call(arguments) var context=Array.prototype.shift.call(arguments) // 取剩余的參數(shù)作為arg; 因?yàn)閍rguments是偽數(shù)組, 所以要轉(zhuǎn)化為數(shù)組才能使用數(shù)組方法 var arg=Array.prototype.slice.call(arguments) // 返回一個(gè)新函數(shù) return function () { // 綁定上下文并傳參 self.apply(context, Array.prototype.concat.call(arg, Array.prototype.slice.call(arguments))) }}
3. 最長(zhǎng)公共子串
function Father () {}function Child () {}// 1\. 原型繼承Child.prototype=new Father()// 2\. 構(gòu)造繼承function Child (name) { Father.call(this, name)}// 3\. 組合繼承function Child (name) { Father.call(this, name)}Child.prototype=new Father()// 4\. 寄生繼承function cloneObj (o) { var clone=object.create(o) clone.sayName=... return clone}// 5\. 寄生組合繼承// 6\. ES6 class extend繼承
4. 最長(zhǎng)公共子序列(LCS動(dòng)態(tài)規(guī)劃)
另一篇
// 父標(biāo)簽animation: antRotate 1.2s infinite linear;// 子標(biāo)簽animation: antSpin 1s infinite linear;@keyframe antSpin { to { opacity: 1 }}@keyframe antRotate { to { transform: rotate(405) }}// animation-delay: 逐個(gè)延遲0.4s
5. 數(shù)組去重,多種方法
6. 實(shí)現(xiàn)一個(gè)函數(shù)功能:sum(1,2,3,4..n)轉(zhuǎn)化為 sum(1)(2)(3)(4)…(n)
// 使用柯里化 + 遞歸
function curry ( fn ) {
var c=(...arg)=> (fn.length===arg.length) ?
fn (...arg) : (...arg1)=> c(...arg, ...arg1)
return c
}
7. 反轉(zhuǎn)二叉樹
var invertTree=function (root) {
if (root !==null) {
[root.left, root.right]=[root.right, root.left]
invertTree(root.left)
invertTree(root.right)
}
return root
}
8. 貪心算法解決背包問題
var items=['A','B','C','D']
var values=[50,220,60,60]
var weights=[5,20,10,12]
var capacity=32 //背包容積
greedy(values, weights, capacity) // 320
function greedy(values, weights, capacity) {
var result=0
var rest=capacity
var sortArray=[]
var num=0
values.forEach((v, i)=> {
sortArray.push({
value: v,
weight: weights[i],
ratio: v / weights[i]
})
})
sortArray.sort((a, b)=> b.ratio - a.ratio)
sortArray.forEach((v, i)=> {
num=parseInt(rest / v.weight)
rest -=num * v.weight
result +=num * v.value
})
return result
}
9. 輸入一個(gè)遞增排序的數(shù)組和一個(gè)數(shù)字S,在數(shù)組中查找兩個(gè)數(shù),使得他們的和正好是S,如果有多對(duì)數(shù)字的和等于S,輸出兩個(gè)數(shù)的乘積最小的。
function FindNumbersWithSum(array, sum)
{
var index=0
for (var i=0; i < array.length - 1 && array[i] < sum / 2; i++) {
for (var j=i + 1; j < array.length; j++) {
if (array[i] + array[j]===sum) return [array[i], array[j]]
}
//index=array.indexOf(sum - array[i], i + 1)
// if (index !==-1) {
// return [array[i], array[index]]
//}
}
return []
10. 二叉樹各種(層序)遍歷
深度廣度遍歷
// 根據(jù)前序和中序重建二叉樹
/* function TreeNode(x) {
this.val=x;
this.left=null;
this.right=null;
} */
function reConstructBinaryTree(pre, vin)
{
var result=null
if (pre.length===1) {
result={
val: pre[0],
left: null,
right: null
}
} else if (pre.length > 1) {
var root=pre[0]
var vinRootIndex=vin.indexOf(root)
var vinLeft=vin.slice(0, vinRootIndex)
var vinRight=vin.slice(vinRootIndex + 1, vin.length)
pre.shift()
var preLeft=pre.slice(0, vinLeft.length)
var preRight=pre.slice(vinLeft.length, pre.length)
result={
val: root,
left: reConstructBinaryTree(preLeft, vinLeft),
right: reConstructBinaryTree(preRight, vinRight)
}
}
return result
}
// 遞歸
// 前序遍歷
function prevTraverse (node) {
if (node===null) return;
console.log(node.data);
prevTraverse(node.left);
prevTraverse(node.right);
}
// 中序遍歷
function middleTraverse (node) {
if (node===null) return;
middleTraverse(node.left);
console.log(node.data);
middleTraverse(node.right);
}
// 后序遍歷
function lastTraverse (node) {
if (node===null) return;
lastTraverse(node.left);
lastTraverse(node.right);
console.log(node.data);
}
// 非遞歸
// 前序遍歷
function preTraverse(tree) {
var arr=[],
node=null
arr.unshift(tree)
while (arr.length) {
node=arr.shift()
console.log(node.root)
if (node.right) arr.unshift(node.right)
if (node.left) arr.unshift(node.left)
}
}
// 中序遍歷
function middleTraverseUnRecursion (root) {
let arr=[],
node=root;
while (arr.length !==0 || node !==null) {
if (node===null) {
node=arr.shift();
console.log(node.data);
node=node.right;
} else {
arr.unshift(node);
node=node.left;
}
}
}
// 廣度優(yōu)先-層序遍歷
// 遞歸
var result=[]
var stack=[tree]
var count=0
var bfs=function () {
var node=stack[count]
if (node) {
result.push(node.value)
if (node.left) stack.push(node.left)
if (node.right) stack.push(node.right)
count++
bfs()
}
}
bfs()
console.log(result)
// 非遞歸
function bfs (node) {
var result=[]
var queue=[]
queue.push(node)
while (queue.length) {
node=queue.shift()
result.push(node.value)
node.left && queue.push(node.left)
node.right && queue.push(node.right)
}
return result
}
11. 各種排序
// 插入排序
function insertSort(arr) {
var temp
for (var i=1; i < arr.length; i++) {
temp=arr[i]
for (var j=i; j > 0 && temp < arr[j - 1]; j--) {
arr[j]=arr[j - 1]
}
arr[j]=temp
}
return arr
}
console.log(insertSort([3, 1, 8, 2, 5]))
// 歸并排序
function mergeSort(array) {
var result=array.slice(0)
function sort(array) {
var length=array.length
var mid=Math.floor(length * 0.5)
var left=array.slice(0, mid)
var right=array.slice(mid, length)
if (length===1) return array
return merge(sort(left), sort(right))
}
function merge(left, right) {
var result=[]
while (left.length || right.length) {
if (left.length && right.length) {
if (left[0] < right[0]) {
result.push(left.shift())
} else {
result.push(right.shift())
}
} else if (left.length) {
result.push(left.shift())
} else {
result.push(right.shift())
}
}
return result
}
return sort(result)
}
console.log(mergeSort([5, 2, 8, 3, 6]))
// 二分插入排序
function twoSort(array) {
var len=array.length,
i,
j,
tmp,
low,
high,
mid,
result
result=array.slice(0)
for (i=1; i < len; i++) {
tmp=result[i]
low=0
high=i - 1
while (low <=high) {
mid=parseInt((high + low) / 2, 10)
if (tmp < result[mid]) {
high=mid - 1
} else {
low=mid + 1
}
}
for (j=i - 1; j >=high + 1; j--) {
result[j + 1]=result[j]
}
result[j + 1]=tmp
}
return result
}
console.log(twoSort([4, 1, 7, 2, 5]))
12. 使用尾遞歸對(duì)斐波那契優(yōu)化
遞歸非常耗費(fèi)內(nèi)存,因?yàn)樾枰瑫r(shí)保存成千上百個(gè)調(diào)用幀,很容易發(fā)生“棧溢出”錯(cuò)誤(stack overflow)。但對(duì)于尾遞歸來說,由于只存在一個(gè)調(diào)用幀,所以永遠(yuǎn)不會(huì)發(fā)生“棧溢出”錯(cuò)誤。
// 傳統(tǒng)遞歸斐波那契, 會(huì)造成超時(shí)或溢出
function Fibonacci (n) {
if ( n <=1 ) {return 1};
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
Fibonacci(10) // 89
Fibonacci(100) // 超時(shí)
Fibonacci(500) // 超時(shí)
// 使用尾遞歸優(yōu)化, 可規(guī)避風(fēng)險(xiǎn)
function Fibonacci2 (n , ac1=1 , ac2=1) {
if( n <=1 ) {return ac2};
return Fibonacci2 (n - 1, ac2, ac1 + ac2);
}
Fibonacci2(100) // 573147844013817200000
Fibonacci2(1000) // 7.0330367711422765e+208
Fibonacci2(10000) // Infinity
13. 兩個(gè)升序數(shù)組合并為一個(gè)升序數(shù)組
function sort (A, B) {
var i=0, j=0, p=0, m=A.length, n=B.length, C=[]
while (i < m || j < n) {
if (i < m && j < n) {
C[p++]=A[i] < B[j] ? A[i++] : B[j++]
} else if (i < m) {
C[p++]=A[i++]
} else {
C[p++]=B[j++]
}
}
return C
}
1. node的router是什么
2. 數(shù)據(jù)庫索引是啥
3. 瀏覽器的事件循環(huán)和node事件循環(huán)有什么區(qū)別?
以上就是前端面試題全面整理-帶解析 涵蓋(css、js、瀏覽器、vue、react、移動(dòng)web、前端性能、算法、node)的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注html中文網(wǎng)其它相關(guān)文章!
我是@半糖學(xué)前端 ,專注前端技術(shù)領(lǐng)域分享,一個(gè)前端從業(yè)者,關(guān)注我和我一起學(xué)習(xí),共同進(jìn)步!
對(duì)于八寶兩個(gè)字我們都不陌生,日常經(jīng)常了解的應(yīng)該屬八寶粥、臘八粥等,這些都是用一些對(duì)人體極好的營(yíng)養(yǎng)物質(zhì)來熬制成粥之后,在進(jìn)行使用,既能夠滿足挑剔的味蕾,又能夠很好的強(qiáng)身健體,清淡的流失對(duì)于生病的人來說也是非常推薦的食物,因此,八寶成為了我們?nèi)粘5某S闷罚贿^除了上述所提到的八寶粥之外,龍井八寶茶也是非常有名的,今天小編就給大家介紹一下關(guān)于龍井八寶茶有哪些功效。
龍井八寶茶有哪些功效?
首先,想要了解龍井八寶茶,就要知道八寶茶有哪八寶,其實(shí),八寶分別是龍井茶、陳皮、枸杞、干桂圓、紅棗、山楂、菊花以及冰糖,這八寶隨便拿出一樣來都是對(duì)人體能夠產(chǎn)生很多功效的滋補(bǔ)品,而將這八種食材相融合成為一道佳肴之后,便是偏向于保健的一類養(yǎng)生茶,但是雖然看著多,做起來卻是非常的簡(jiǎn)單的。
八寶茶,用八種配料加入蓋碗之后,再用滾燙的水進(jìn)行沖泡,然后讓配料在蓋碗中進(jìn)行翻滾,讓配料慢慢與水融合,然后蓋上蓋,靜待幾分鐘之后,便可以進(jìn)行享用了,因此,對(duì)于身體不好的人來說,常服用一些這樣的保健茶,對(duì)于身體是有很強(qiáng)大的功效的。
八寶茶在冬天飲用是最佳的時(shí)間,因?yàn)槎竞涓稍铮瑢?duì)于身體不好的人來說,冬天會(huì)出現(xiàn)免疫力下降,手腳冰涼等癥狀,八寶茶中枸杞和紅棗都能起到一定的補(bǔ)充作用,而菊花能夠降火消暑,而龍井雖然只是這八分之一,卻仍舊是占據(jù)了很重要的位置,龍井的濃厚茶香,再配以冰糖的甜度可口,能夠中和八寶茶的口感,讓八寶茶更是一種飲用。
龍井八寶茶有哪些功效?
龍井八寶茶營(yíng)養(yǎng)非常的豐富,而且功效也是非常的強(qiáng)大,能夠起到清火、降噪、養(yǎng)顏、固本保元的作用,特別是對(duì)于身體虛弱,四肢無力以及消化不良的人來說,在飯后飲一杯龍井八寶茶,可以說是一件非常幸福的事情了。
龍井八寶茶雖然看似簡(jiǎn)單,食材也是非常容易買到,但是功效卻是普通茶飲料的好幾倍,不論春夏秋冬,都可以正常飲用,特別是在節(jié)日之后,因?yàn)楣?jié)日之時(shí)人們都會(huì)暴飲暴食,難免造成消化不良等毛病,在飯后準(zhǔn)備一杯龍井八寶茶,能夠疏通胃腸,促進(jìn)胃功能,從而對(duì)身體進(jìn)行一個(gè)補(bǔ)充。
因此,綜上所述,龍井八寶茶對(duì)于人們來說是非常有好處的,日常如果在家多時(shí),可以學(xué)著做一做龍井八寶茶,五顏六色的色彩,也會(huì)讓人們的食欲大增,不過還是要特別注意,以上的食材有沒有自身的身體條件不適宜飲用的,如果有還是要特別留意一下的。
文章來源longjing100.com,本文鏈接http://www.longjing100.com/a/gongxiao/13616.html
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。