前端面試問題
本套面試題由淺入深提問;
測試分支:externalChannels-frontEnd-test
測試文件:frontEndTest.html
底層原理
- javascript數(shù)據(jù)類型有哪幾種?
null、undefiend、number、string、boolean、object五種類型;
- 如何確定一個(gè)值到底是什么類型,例如使用instanceof運(yùn)算符;
1.三種方法確認(rèn)值是什么類型,typeof、instanceof、Object.prototype.toString
2.typeof運(yùn)算符可以返回一個(gè)值的數(shù)據(jù)類型(number、string、boolean、object),object對象typeof無法區(qū)分。
3.instanceof 運(yùn)算符用于檢測構(gòu)造函數(shù)的 prototype 屬性是否出現(xiàn)在某個(gè)實(shí)例對象的原型鏈上(new String() instanceof String)。
4.Object.prototype.toString >>Object.prototype.toString('') =>[object Object
- null和undefined分別代表意思?null == undefined?兩個(gè)等于和三個(gè)等于的區(qū)別?
null和undefined分別代表空值和未定義、null == undefined=true、比較運(yùn)算符和相等運(yùn)算符
- 什么是作用域?作用域有那幾種?作用域鏈有什么特點(diǎn)?
var i = 5;
function func() {
console.log(i);
if (true) {
var i = 6;
}
}
func(); // undefined
作用域:它是指對某一變量和方法具有訪問權(quán)限的代碼空間
作用域:作用域分為全局作用域和局部作用域
作用域鏈的特點(diǎn)就是,先在自己的變量范圍中查找,如果找不到,就會(huì)沿著作用域往上找
// 作用域的特點(diǎn)就是,先在自己的變量范圍中查找,如果找不到,就會(huì)沿著作用域往上找。
var a = 1;
function b(){
var a = 2;
function c(){
var a = 3;
console.log(a);
}
c(); //3
}
b();
使用Es6的什么屬性能解決作用域問題?
let const 配合 塊級作用域
- 什么是閉包?什么場景下使用閉包函數(shù)?使用ES6的屬性能解決?
什么是閉包:閉包是指有權(quán)訪問另外一個(gè)函數(shù)作用域中的變量的函數(shù)
閉包函數(shù):避免全局污染、生成一個(gè)新的函數(shù)作用域
function outer() {
var result = [];
for (var i = 0; i<10; i++){
result[i] = function (num) {
return function() {
console.info(num); // 此時(shí)訪問的num,是上層函數(shù)執(zhí)行環(huán)境的num,數(shù)組有10個(gè)函數(shù)對象,每個(gè)對象的執(zhí)行環(huán)境下的number都不一樣
}
}(i)
}
return result
}
使用ES6的屬性能解決:let const
- 什么是原型鏈?原型鏈的最頂層為什么?
在javascript中,實(shí)例對象與原型之間的鏈接,叫做原型鏈。其基本思想是利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法。然后層層遞進(jìn),就構(gòu)成了實(shí)例與原型的鏈條,這就是所謂原型鏈的基本概念
原型鏈的最頂層:為null
- 原型鏈具體能干什么?
繼承
- ES6語法可以實(shí)現(xiàn)繼承?
class 中的 extends
- this指向問題?
function test(){
var user = "中歐財(cái)富";
console.log(this.user); //undefined
console.log(this); //Window
}
test();
-----------------
var test1 = {
user:'中歐財(cái)富',
fn:function(){
console.log(this.user);
}
};
test1.fn(); //中歐財(cái)富
----------------
var test2 = {
user:'中歐財(cái)富',
fn:function(){
console.log(this.user);
}
};
const tempFn = test2.fn;
tempFn(); //window
//怎么解決this指向的問題?如何用ES6解決?
ES5解決方案:閉包
ES6解決方案:箭頭函數(shù)、bind
- 聊一聊淺拷貝和深拷貝?
淺拷貝使用方法有:Object.assign()、Array.prototype.slice、擴(kuò)展運(yùn)算符..
- 深拷貝實(shí)現(xiàn),遞歸實(shí)現(xiàn)深拷貝
function cloneObject(obj){
var newObject = {};
if(typeof obj !== object){
return obj;
}else{
for(var attr in obj){
newObject = cloneObject(obj[attr]);
}
}
return newObject;
}
- call和apply的區(qū)別,它們的作用是什么?
call:接受多個(gè)參數(shù)、apply接受一個(gè)數(shù)組;作用:指定執(zhí)行的上下文以及繼承;
事件
- 什么是事件委托?事件委托的應(yīng)用場景?
- 事件委托(delegate)也稱為事件托管或事件代理,就是把目標(biāo)節(jié)點(diǎn)的事件綁定到祖先節(jié)點(diǎn)上
- 事件委托的應(yīng)用場景:處理多個(gè)相同元素綁定同一個(gè)事件,可以提升到父級元素處理
- 什么是事件冒泡和事件捕獲
1.事件捕獲階段:事件從最上一級標(biāo)簽開始往下查找,直到捕獲到事件目標(biāo)(target)。
2.事件冒泡階段:事件從事件目標(biāo)(target)開始,往上冒泡直到頁面的最上一級標(biāo)簽。
瀏覽器
- 瀏覽器解析網(wǎng)頁的工作原理?
- 瀏覽器一邊下載 HTML 網(wǎng)頁,一邊開始解析。也就是說,不等到下載完,就開始解析。
- 解析過程中,瀏覽器發(fā)現(xiàn)<script>元素,就暫停解析,把網(wǎng)頁渲染的控制權(quán)轉(zhuǎn)交給 JavaScript 引擎。
- 如果<script>元素引用了外部腳本,就下載該腳本再執(zhí)行,否則就直接執(zhí)行代碼。
- JavaScript 引擎執(zhí)行完畢,控制權(quán)交還渲染引擎,恢復(fù)往下解析 HTML 網(wǎng)頁。
- 瀏覽器渲染引擎工作原理?
- 解析代碼:HTML 代碼解析為 DOM,CSS 代碼解析為 CSSOM(CSS Object Model)。
- 對象合成:將 DOM 和 CSSOM 合成一棵渲染樹(render tree)。
- 布局:計(jì)算出渲染樹的布局(layout)。
- 繪制:將渲染樹繪制到屏幕。
- 重流和重繪
- 渲染樹轉(zhuǎn)換為網(wǎng)頁布局,稱為“布局流”(flow);布局顯示到頁面的這個(gè)過程,稱為“繪制”(paint)。它們都具有阻塞效應(yīng),并且會(huì)耗費(fèi)很多時(shí)間和計(jì)算資源。
- 頁面生成以后,腳本操作和樣式表操作,都會(huì)觸發(fā)“重流”(reflow)和“重繪”(repaint)。用戶的互動(dòng)也會(huì)觸發(fā)重流和重繪,比如設(shè)置了鼠標(biāo)懸停(a:hover)效果、頁面滾動(dòng)、在輸入框中輸入文本、改變窗口大小等等。
- 重流和重繪并不一定一起發(fā)生,重流必然導(dǎo)致重繪,重繪不一定需要重流。比如改變元素顏色,只會(huì)導(dǎo)致重繪,而不會(huì)導(dǎo)致重流;改變元素的布局,則會(huì)導(dǎo)致重繪和重流。
- 什么是CORS,怎么解決CORS問題?
- CORS(跨域資源共享)、服務(wù)端配置
Access-Control-Allow-Origin:*- 使用其他方式解決JSONP
- 使用代理
- http請求有那幾種?常用的有哪幾種?Get和Post的區(qū)別?Get和POST應(yīng)用?
- http請求有那幾種:GET、HEAD、POST、PUT、DELETE、OPTIONS
- 常用的有哪幾種:GET和POSTo,URL對鏈接有字符限制;POST:表單請求,對參數(shù)沒有限制;
- Get和POST應(yīng)用:Get一般用于無敏感并且參數(shù)少的功能、POST比GET稍微安全一點(diǎn),可以用于登錄、購買...
- 是否了解發(fā)送請求的預(yù)檢請求,每一次請求一個(gè)接口總會(huì)多發(fā)出一個(gè)請求;
預(yù)檢查接口主要去詢問服務(wù)器是否支持當(dāng)前請求,如果不支持網(wǎng)頁會(huì)直接報(bào)錯(cuò),如果支持直接返回結(jié)果。
- history的push和history的replace區(qū)別,主要應(yīng)用在那一塊?
- push a->b->c ; 返回c->b-a;
- replace a-b-c; c->返回到更上級;
存儲(chǔ)
- cookie與Storage,什么是cookie?什么情況下使用Storage?
cookie使用一般在于老版本的瀏覽器使用,常見用的最多的是PC端,cookie容量4kb(保存數(shù)量15~20個(gè)左右),主要用于保存用戶個(gè)性化信息,購物車
Storage 能存儲(chǔ)大量的數(shù)據(jù),適用于前端;
異步操作
- js處理異步操作的有那幾種方式?舉例:傳統(tǒng)的回調(diào)函數(shù);
- 傳統(tǒng)的回調(diào)函數(shù)
- 事件監(jiān)聽(Events)
- Promise
- generator+回調(diào)函數(shù)
- generator+Promise
- async/await
怎么做前端的SEO
- 設(shè)置TDK和服務(wù)端SSR的渲染;
ES6
- 說一下自己常用的es6功能?
const、let、箭頭函數(shù)、字符串模版、class、extends.....
- export和export default的區(qū)別?
export default xxx
import xxx from './'
export xxx
import {xxx} from './'
業(yè)務(wù)
- 能否講解一下你具體負(fù)責(zé)的這一塊的業(yè)務(wù)流程嗎?
- 如果交給你一個(gè)需求,你應(yīng)該怎么去入手?
- 日常開發(fā)中解決了什么業(yè)務(wù)難點(diǎn)問題?怎么解決的能細(xì)說嗎?
- 日常開發(fā)中如何去排查和定位問題?
- 請問一下你們公司的發(fā)布前端應(yīng)用的流程?
- 如何優(yōu)化PC端或者移動(dòng)端的性能?從那方面入手的?
上層應(yīng)用(框架)
- 什么是SPA(單頁面應(yīng)用程序),什么是MPA(多頁面應(yīng)用程序)?一般用于?
MPA:由多個(gè)完整頁面構(gòu)成、SAP:一個(gè)外殼頁面和多個(gè)頁面片段構(gòu)成
MPA:一般適用于PC(利于SEO)、SPA:一般適用于移動(dòng)端
- 市面上的vuex、mobx、redux...數(shù)據(jù)狀態(tài)管理庫作用是什么?它們的原理是什么?
根據(jù)使用者情況詳細(xì)了解;
- 市面上的vue-router和react-router是通過什么實(shí)現(xiàn)的?
通過hash(location.hash+hashchange)、history(history.pushState()+popState)
- 怎么對路由進(jìn)行按需加載?
react使用react-loadabl進(jìn)行路由按需加載、import、require.ensure
- 如果我想做權(quán)限管理,應(yīng)該怎么實(shí)現(xiàn)?
路由守衛(wèi)(路由攔截)中處理。
- 聊聊你們常用的基于HTTP網(wǎng)絡(luò)請求庫? 網(wǎng)絡(luò)請求庫中的發(fā)送http請求前事件和數(shù)據(jù)返回事件的應(yīng)場景?
網(wǎng)絡(luò)請求庫:axios、fetch
發(fā)送http請求前事件和數(shù)據(jù)返回事件:如:發(fā)送前合并參數(shù)、數(shù)據(jù)返回后對數(shù)據(jù)進(jìn)行處理等等...
組件
- 現(xiàn)代的前端框架React、Vue以及Angular為什么都要使用組件化的概念?
高復(fù)用、可擴(kuò)展、易管理
- 在開發(fā)過程中有對項(xiàng)目中的組件進(jìn)行分類嗎,比如:改變按鈕顏色的組件,我們稱為功能性組件,請問你們也有類似的組件分類嗎?
ui組件、功能組件、業(yè)務(wù)組件
簡單算法
- 數(shù)組去重
var arr = ['1', '1', '2', '3', '4', '5', '6', '7', '7', '8'];
//方案一
function unique(arr) {
var _tempArr = [];
for (var i = 0; i < arr.length; i++) {
if (_tempArr.indexOf(arr[i]) === -1) {
_tempArr.push(arr[i]);
}
}
return _tempArr;
}
console.log(unique(arr));
//方案二
function unique1(arr) {
for (var i = 0; i < arr.length; i++) {
for (var j = i + 1; j < arr.length; j++) {
if (arr[i] === arr[j]) {
arr.splice(j, 1);
j--;
}
}
}
return arr;
}
console.log(unique1(arr));
//還有很多種排序方案
- 數(shù)據(jù)倒序
var arr = ['a', '1', '2', '3', '4', '5', '6', '7', '7', 'z','s'];
//方案一
function sort(arr) {
var _tempArray = [];
for (var i = arr.length - 1; i >= 0; i--) {
_tempArray.push(arr[i]);
}
return _tempArray;
}
console.log(sort(arr));
//方案二
function sort1(arr) {
for (var i = 0; i < (arr.length / 2); i++) {
var temp = arr[i];
arr[i] = arr[arr.length - i - 1];
arr[arr.length - i - 1] = temp;
}
return arr;
}
console.log(sort1(arr));