1、如何理解執(zhí)行上下文
JavaScript執(zhí)行上下文(context)主要指代碼執(zhí)行環(huán)境的抽象概念集惋。執(zhí)行上下文分為三種:
- 全局執(zhí)行上下文
- 函數(shù)執(zhí)行上下文
- eval執(zhí)行上下文
每一段js代碼執(zhí)行奶赠,都會(huì)先創(chuàng)建一個(gè)上下文環(huán)境。
2侧戴、如何理解作用域鏈
前沿知識(shí):js代碼執(zhí)行前會(huì)創(chuàng)建上下文環(huán)境,這個(gè)上下文環(huán)境包含了變量跌宛、作用域鏈和this.
簡(jiǎn)單理解就是從當(dāng)前環(huán)境向父級(jí)一層一層查找變量的過(guò)程稱之為作用域鏈酗宋。
// 正常訪問(wèn)
var lan = 'zh';function hello(){ var name = '前端未來(lái)';}
console.log(name)//很明顯'undefined'
//換成閉包
function hello(){ var name = '前端未來(lái)'; function demo(){ console.log(name)//打印:前端未來(lái) }}
解釋:當(dāng)我們?cè)诤瘮?shù)hello里面打印name的時(shí)候疆拘,會(huì)先在hello作用域中查找蜕猫,如果沒(méi)有找到就去hello的父級(jí)作用域中查找。
3哎迄、如何理解原型鏈
每個(gè)函數(shù)都擁有一個(gè)prototype屬性回右,每個(gè)函數(shù)實(shí)例對(duì)象都擁有一個(gè)proto屬性,而這個(gè)屬性指向了函數(shù)的prototype漱挚,當(dāng)我們?cè)L問(wèn)實(shí)例對(duì)象的屬性或者方法時(shí)翔烁,會(huì)先從自身構(gòu)造函數(shù)中查找,如果沒(méi)有就通過(guò)proto去原型中查找旨涝,這個(gè)查找的過(guò)程我們稱之為原型鏈蹬屹。(跟作用域鏈有點(diǎn)像)
// 正常訪問(wèn)
var lan = 'zh';function hello(){ var name = '前端未來(lái)';}
console.log(name)//很明顯'undefined'
// 換成閉包
function hello(){ var name = '前端未來(lái)'; function demo(){ console.log(name)//打印:前端未來(lái) }}
通過(guò)截圖,我們可以看到cat實(shí)例對(duì)象proto指向了Animal慨默,當(dāng)cat沒(méi)有age的時(shí)候贩耐,會(huì)通過(guò)proto到原型上查找,如果原型上依然沒(méi)有厦取,會(huì)繼續(xù)向Object上查找潮太。
4、什么是閉包
簡(jiǎn)單理解就是函數(shù)中嵌套函數(shù)虾攻。我們都知道局部變量我們是無(wú)法訪問(wèn)的铡买,但是通過(guò)閉包可以做到。
// 正常訪問(wèn)
var lan = 'zh';function hello(){ var name = '前端未來(lái)';}console.log(name)
//很明顯'undefined'
// 換成閉包
function hello(){ var name = '前端未來(lái)'; function demo(){ console.log(name)//打遇俊:前端未來(lái) }}
以上幾個(gè)基礎(chǔ)面試題都是密切關(guān)聯(lián)的奇钞,理解其中一個(gè),基本就能理解剩下幾個(gè)
5朋沮、繼承有哪些方法
- 原型繼承
- 構(gòu)造繼承
- 實(shí)例繼承
- call/apply繼承(組合繼承)
- ES6 使用class extends繼承
6蛇券、什么是深/淺拷貝,有哪些實(shí)現(xiàn)方式
JS數(shù)據(jù)類型分別基本數(shù)據(jù)類型和引用數(shù)據(jù)類型樊拓,基本數(shù)據(jù)類型保存的是值纠亚,引用類型保存的是引用地址(this指針)。淺拷貝共用一個(gè)引用地址筋夏,深拷貝會(huì)創(chuàng)建新的內(nèi)存地址蒂胞。
淺拷貝方法
- 直接對(duì)象復(fù)制
- Object.assign
深拷貝
- JSON.stringify轉(zhuǎn)為字符串再JSON.parse
- 深度遞歸遍歷
7、如何準(zhǔn)確判斷一個(gè)對(duì)象是數(shù)組
面試官希望的答案:Object.prototype.toString.call([]) 返回 "[object Array]"
擴(kuò)展答案
- [].slice (能力判斷 )
- [] instanceof Array(類型判斷)
- [].proto === Array.prototype
- Array.isArray([]) 存在兼容問(wèn)題
數(shù)組也是引用類型条篷,通過(guò)typeof依然返回object
8骗随、數(shù)組有哪些常用方法
這個(gè)非常多,說(shuō)起來(lái)也很快赴叹,我主要考察你會(huì)多少鸿染,另外也為了引出下一個(gè)問(wèn)題,slice和splice區(qū)別
- push 末尾添加
- pop 末尾刪除
- shift 首部刪除
- unshift 首部添加
- concat 數(shù)組合并
- join 數(shù)組元素 通過(guò)連接符 連接
- reverse 數(shù)組反轉(zhuǎn)
- sort 數(shù)組排序
- map/forEach/filter/indexOf/includes/slice/splice
slice表示截取,slice(start,end)不改變?cè)瓟?shù)組乞巧,返回新數(shù)組涨椒。
splice表示刪除,splice(start,length,item)绽媒,會(huì)改變?cè)瓟?shù)組蚕冬,從某個(gè)位置開(kāi)始刪除多個(gè)元素,并可以插入新的元素是辕。
9囤热、DOM節(jié)點(diǎn)創(chuàng)建和修改有哪些常用API
創(chuàng)建節(jié)點(diǎn)
- createElement
- createTextNode
- createDocumentFragment(臨時(shí)節(jié)點(diǎn))
修改節(jié)點(diǎn)
- appendChildparent.appendChild(child)
- insertBefore parentNode.insertBefore(newNode,refNode);
- removeChild parent.removeChild(node)
- replaceChild
10、CSS清除浮動(dòng)有哪些方法
- 父級(jí)元素設(shè)置高度获三,手動(dòng)撐開(kāi)
- 浮動(dòng)元素結(jié)尾增加空標(biāo)簽旁蔼,設(shè)置clear:both
- 父元素設(shè)置overflow:hidden
- 父元素添加偽類:after和zoom
11锨苏、CSS選擇器優(yōu)先級(jí)
!import > 內(nèi)聯(lián)樣式(style) > ID選擇器 > 類/屬性/偽類 > 元素/關(guān)系
12、CSS實(shí)現(xiàn)三列布局(左右固定寬度牌芋,中間自適應(yīng))
- CSS浮動(dòng)
第一個(gè)float:left蚓炬,第二個(gè)float:right松逊,第三個(gè)設(shè)置margin-left和margin-right
- 絕對(duì)定位法
第一個(gè)定位到left躺屁,第二個(gè)定位到right,第三個(gè)設(shè)置margin-left和margin-right
- flex布局
.left{ width:200px; 或者 flex:0 0 200px;}.right{ width:200px; 或者 flex:0 0 200px;}.center{ flex:1;}
- 阿里圣杯布局
14经宏、談一下flex布局
flex是一種彈性布局犀暑,包含flex-container和flex-item.
常用的屬性包括flex-direction、flex-wrap烁兰、justify-content耐亏、align-items
水平居中 justify-content:center 水平兩頭居中 justify-content:space-between 垂直居中 align-items:center
15、談一下盒模型
盒模型包括:content,padding,border,margin
盒模型分為:IE盒模型和標(biāo)準(zhǔn)w3c盒模型
IE盒模型寬度包含了padding和border沪斟,w3c盒模型寬度就是內(nèi)容寬度广辰。
16、transition動(dòng)畫和animation有什么區(qū)別
他們雖然都可以做出動(dòng)畫效果主之,但是transition主要做簡(jiǎn)單的過(guò)渡效果择吊,而animation可以做復(fù)雜的動(dòng)畫效果,在語(yǔ)法和用法上有非常大的區(qū)別槽奕。
17几睛、H5自適應(yīng)方案
H5自適應(yīng)方案大家在網(wǎng)速能找到很多,我個(gè)人推薦一種我非常喜歡的方式粤攒,就是rem. rem是一種相對(duì)單位所森,它基于html的font-size值來(lái)進(jìn)行調(diào)整。
通常我們以750為基準(zhǔn)夯接,我們會(huì)在header中嵌套一段js腳本焕济,獲取手機(jī)網(wǎng)頁(yè)分辨率尺寸除以375,為了方便計(jì)算盔几,我們假設(shè)750像素下1rem = 100px晴弃;所以 我們除以375后需要乘以50.
18、call/apply/bind作用和區(qū)別
他們都可以改變函數(shù)的作用域问欠。
- call/apply可以直接執(zhí)行該函數(shù)肝匆,而bind不會(huì)立刻執(zhí)行
- call/apply作用類似,都可以改變指針和執(zhí)行函數(shù)顺献,區(qū)別在于傳參不同旗国,call需要單個(gè)傳參,apply通過(guò)數(shù)組傳參
19注整、觀察者和發(fā)布訂閱者區(qū)別
他們都屬于觀察者模式能曾,只不過(guò)有不同的實(shí)現(xiàn)方法度硝。發(fā)布訂閱相比于觀察者多了一個(gè)調(diào)度中心,發(fā)布者通過(guò)調(diào)度中心向訂閱者發(fā)布消息寿冕。觀察者模式中目標(biāo)和觀察者相互依賴蕊程,觀察者訂閱目標(biāo)主題,當(dāng)目標(biāo)發(fā)生變化后驼唱,會(huì)通知對(duì)應(yīng)觀察者藻茂。
20、瀏覽器解析渲染頁(yè)面過(guò)程
[圖片上傳失敗...(image-5a7918-1593959361842)]
- 解析HTML玫恳,生成DOM樹(shù)
- 解析CSS辨赐,生成CSSOM樹(shù)
- 將DOM樹(shù)和CSSOM樹(shù)關(guān)聯(lián),生成渲染樹(shù)(Render Tree)
- 布局render樹(shù)(Layout/reflow)京办,負(fù)責(zé)各元素尺寸掀序、位置的計(jì)算
- 繪制render樹(shù)(paint),繪制頁(yè)面像素信息
- 將像素發(fā)送給GPU惭婿,展示在頁(yè)面上不恭。(Display)
21、談一下EventLoop
這其中大家需要了解幾個(gè)概念:調(diào)用棧财饥、同步/異步任務(wù)换吧、宏任務(wù)/微任務(wù)
JavaScript本身是單線程,也就是同一時(shí)刻只能干一件事佑力,JS任務(wù)包含了同步任務(wù)和異步任務(wù)式散,遇到執(zhí)行函數(shù)會(huì)將其放入調(diào)用棧(先進(jìn)后出)中,遇到setTimeout/setInterval等異步任務(wù)時(shí)打颤,會(huì)把它放入到消息隊(duì)列中暴拄,等主線程的任務(wù)執(zhí)行完成以后,再回過(guò)頭執(zhí)行消息隊(duì)列中的異步任務(wù)编饺,如果異步任務(wù)中仍然有異步任務(wù)乖篷,會(huì)繼續(xù)放入消息隊(duì)列,以此類推透且,便形成了一個(gè)事件循環(huán)撕蔼。
異步任務(wù):
- setTimeout
- setInterval
異步任務(wù)又分為宏任務(wù)和微任務(wù),promise就屬于微任務(wù).
22秽誊、GET和POST有什么區(qū)別
大小方面
GET傳輸一般2K-8K鲸沮,IE限制2K,锅论,POST沒(méi)有大小限制
安全方面
GET通過(guò)url明文傳輸讼溺,POST通過(guò)body傳輸,本身都不安全最易,因?yàn)镠TTP就是明文傳輸怒坯。
瀏覽器記錄
GET請(qǐng)求瀏覽器會(huì)記錄炫狱,POST不會(huì)
瀏覽器后退
GET無(wú)害,POST會(huì)再次提交
瀏覽器收藏
GET可以收藏剔猿,POST不可以
瀏覽器緩存
GET可以緩存视译,POST不會(huì)
編碼方式
GET通過(guò)url編碼,POST支持多種編碼
TCP數(shù)據(jù)包
GET產(chǎn)生一個(gè)數(shù)據(jù)包归敬,POST產(chǎn)生2個(gè)數(shù)據(jù)包
使用方式(習(xí)慣上講)
GET主要拉取數(shù)據(jù)酷含,POST主要提交保存數(shù)據(jù)
23、談一下防抖和節(jié)流
防抖和節(jié)流都是希望在同一時(shí)間內(nèi)弄慰,不要重復(fù)觸發(fā)請(qǐng)求第美。一般場(chǎng)景用在搜索和網(wǎng)頁(yè)滾動(dòng)事件中蝶锋。
區(qū)別:
防抖主要是在規(guī)定時(shí)間內(nèi)只觸發(fā)一次陆爽,如果再次調(diào)用,時(shí)間重新計(jì)算扳缕。
節(jié)流主要是在固定時(shí)間內(nèi)只觸發(fā)一次慌闭。比如每間隔1秒觸發(fā)一次。
24躯舔、數(shù)組如何去重
- ES6 Set去重
- 利用Object key去重
- 兩層循環(huán)逐一對(duì)比驴剔,生成新數(shù)組
- indexOf去重
- sort排序,再單層循環(huán)前后對(duì)比
25粥庄、數(shù)組如何排序
- 數(shù)組sort排序
- 冒泡排序(兩層循環(huán)丧失,兩兩互換)
//冒泡排序
function bubbleSort ( data ) {
var temp = 0;
for ( var i = data.length ; i > 0 ; i -- ){
for( var j = 0 ; j < i - 1 ; j++){
if( data[j] > data[j + 1] ){
temp = data[j];
data[j] = data [j+1];
data[j+1] = temp;
}
}
}
return data;
}
- 選擇排序
//選擇排序
function selectionSort( data ) {
for( var i = 0; i< data.length ; i++){
var min = data[i];
var temp;
var index = i;
for( var j = i + 1; j< data.length; j++){
if( data[j] < min ){
min = data[j];
index = j;
}
}
temp = data[i];
data[i] = min;
data[index]= temp;
}
return data;
}
- 插入排序
//插入排序function insertionSort( data ) {
var len = data.length;
for (var i = 1; i < len; i++) {
var key = data[i];
var j = i - 1;
while ( j >= 0 && data[j] > key) {
data[j + 1] = data[j];
j--;
}
data[j + 1] = key;
}
return data;
}
26、談一下常用設(shè)計(jì)模式惜互,并選擇一個(gè)進(jìn)行場(chǎng)景分析
- 單例模式
- 工廠模式
- 觀察者模式
- 適配器模式
在Vue中通過(guò)觀察者模式觸發(fā)視圖更新布讹。Vue2.x通過(guò)Object.defineProperty劫持data數(shù)據(jù),當(dāng)數(shù)據(jù)變化后觸發(fā)setter训堆,setter內(nèi)部通過(guò)訂閱器來(lái)notify消息描验,notify會(huì)調(diào)用watcher更新視圖。
當(dāng)一套前端對(duì)接不同后端服務(wù)時(shí)坑鱼,會(huì)出現(xiàn)數(shù)據(jù)結(jié)構(gòu)不一致情況膘流,這個(gè)時(shí)候可以使用適配器模式來(lái)兼容不同后端,使他以統(tǒng)一的數(shù)據(jù)結(jié)構(gòu)對(duì)接前端鲁沥。
27呼股、談一下for...of
for...of 是ES2015版本引入的語(yǔ)法,它可以遍歷數(shù)組画恰、類數(shù)組彭谁、以及Map/set/字符串等
- 數(shù)組迭代
for (const number of [1,2,5]) { }
- 類數(shù)組迭代
for (const number of arguments) { }
- 字符串迭代
const message = 'hello';
for (const character of message) { }
- map迭代
const map = new Map();
map.set("name", '前端未來(lái)');
map.set("author", '河畔一角');
for(const item of map){ }// 或者for(const [key,val] of map){ }
- Set迭代
const names = new Set(['Tom', 'Jack', 'Lily']);for (let name of names) { }
for...of非常靈活,還有其它例子阐枣,我這兒不再列出马靠。
28奄抽、前端常見(jiàn)攻擊方式
- XSS攻擊
- CSRF攻擊
- Sql注入
- html腳本注入
攻擊原理和方案這兒不再闡述
29、前端有哪些跨域方案
- JSONP跨域(本質(zhì)是JS調(diào)用)
- CORS(后臺(tái)設(shè)置)
- Nginx反向代理(運(yùn)維配置)
跨域是瀏覽器做出的安全限制甩鳄,必須同協(xié)議逞度、同域名、同端口否則會(huì)被瀏覽器block
不常用跨域方案妙啃,我不進(jìn)行列出
30档泽、前端網(wǎng)站常規(guī)優(yōu)化方案
優(yōu)化策略:減少請(qǐng)求次數(shù)、減小資源大小揖赴、提高響應(yīng)和加載速度馆匿、優(yōu)化資源加載時(shí)機(jī)、優(yōu)化加載方式
- 合并燥滑、壓縮渐北、混淆html/css/js文件(webpack實(shí)現(xiàn),減小資源大忻 )
- Nginx開(kāi)啟Gzip赃蛛,進(jìn)一步壓縮資源(減小資源大小)
- 圖片資源使用CDN加速(提高加載速度)
- 符合條件的圖標(biāo)做base64處理(減小資源大胁笃小)
- 樣式表放首部呕臂,JS放尾部(JS單線程,會(huì)阻塞頁(yè)面肪跋;資源加載方式)
- 設(shè)置緩存(強(qiáng)緩存和協(xié)商緩存歧蒋,提高加載速度)
- link或者src添加rel屬性,設(shè)置prefetch或preload可預(yù)加載資源州既。(加載時(shí)機(jī))
- 如果使用了UI組件庫(kù)谜洽,采用按需加載(減小資源大小)
- SPA項(xiàng)目易桃,通過(guò)import或者require做路由按需(減小資源大腥焖觥)
- 服務(wù)端渲染SSR,加快首屏渲染晤郑,利于SEO
- 頁(yè)面使用骨架屏敌呈,提高首頁(yè)加載速度(提高加載速度)
- 使用 JPEG 2000, JPEG XR, and WebP 的圖片格式來(lái)代替現(xiàn)有的jpeg和png,當(dāng)頁(yè)面圖片較多時(shí)造寝,這點(diǎn)作用非常明顯
- 使用圖片懶加載-lazyload