【面經(jīng)系列】一線互聯(lián)網(wǎng)大廠前端面試技巧深入淺出總結(jié)
△?是新朋友嗎?記得先關(guān)注我哦~
一二面(基礎(chǔ)面)
1. 一面基礎(chǔ)面
1.1 面試準(zhǔn)備
1.1.1 個(gè)人簡(jiǎn)歷
基本信息:姓名-年齡-手機(jī)-郵箱-籍貫
工作經(jīng)歷:時(shí)間-公司-崗位-職責(zé)-技術(shù)棧-業(yè)績(jī)(哪些成就)
學(xué)歷:博士 > 碩士 > 本科 > 大專
工作經(jīng)歷:時(shí)間-公司-崗位-職責(zé)-技術(shù)棧-業(yè)績(jī)
開源項(xiàng)目:GitHub和說明
1.2.2 自我陳述
1.2.2.1 把我面試的溝通方向(別把自己帶到坑里面)
答:我平時(shí)喜歡研究一些網(wǎng)站,并對(duì)一些技術(shù)的原理和好玩的點(diǎn)感興趣,我自己也喜歡思考,也喜歡嘗試探索有沒有更好的方式和實(shí)現(xiàn)。(有所收留,不要全部說出來,稍微留一點(diǎn)懸念留作面試官來提問)
1.2.2.2 豁達(dá)、自信的適度發(fā)揮
答:適當(dāng)自信,向自己擅長(zhǎng)的方向上面來引路;要讓面試官來欣賞我,而不是來鄙視他。
1.2.2.3 自如談興趣
(豁達(dá)自信,適當(dāng)收住),巧妙演示實(shí)例,適時(shí)討論疑問(不知道的問題請(qǐng)求指導(dǎo)一下,如何去解決,不要說不知道,或者不了解)
1.2.2.4 節(jié)奏要適宜
切忌小聰明(盡量把問題的所有實(shí)現(xiàn)方法都寫出來,表現(xiàn)出來的是熟練)
1.2 面試實(shí)戰(zhàn)
[!NOTE]
方向要對(duì),過程要細(xì)(性能優(yōu)化,過程詳細(xì))
膽子要大、心態(tài)要和(算法題認(rèn)真思考,認(rèn)真使勁想;敢于承擔(dān)責(zé)任,不要輕易放棄)
2. CSS相關(guān)
2.1 頁面布局
2.1.1 如何實(shí)現(xiàn)垂直居中布局呢?
1.已知寬高
/*v1*/
.container {
position: absolute;
left: 50%;
top: 50%;
marigin-left: -width / 2;
marigin-top: -width / 2;
}
/*v2*/
.container {
position: absolute;
top: calc(50% - 5em);
left: calc(50% - 9em);
}
2.未知寬高
/*v1*/
.container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/*v2:flex+ auto*/
.wrapper {
dislay: flex;
}
.content {
margin: auto;
}
/*v3. 父元素居中*/
.wrapper {
display: flex;
/* 盒子橫軸的對(duì)齊方式 */
justify-content: center;
/* 盒子縱軸的對(duì)齊方式 */
align-items: center;
}
/*v4.body內(nèi)部居中*/
.content {
/* 1vh = 1% * 視口高度 */
margin: 50vh auto;
transform: translateY(-50%);
}
2.1.2 如何實(shí)現(xiàn)水平居中布局呢?
如果需要居中的元素為常規(guī)流中 inline / inline-block 元素,為父元素設(shè)置 text-align: center;
父元素上設(shè)置 text-align: center; 居中元素上margin 為 auto。
如果元素positon: absolute; 那么
0)設(shè)置父元素postion: relative
1)為元素設(shè)置寬度,
2)偏移量設(shè)置為 50%,
3)偏移方向外邊距設(shè)置為元素寬度一半乘以-1
2.1.3 如何實(shí)現(xiàn)三欄布局呢?
left和right寫在center前面,并且分別左右浮動(dòng);
左右區(qū)域分別postion:absolute,固定到左右兩邊;中間的這個(gè)div因?yàn)槭菈K級(jí)元素,所以在水平方向上按照他的包容塊自動(dòng)撐開。
父元素display: table;并且寬度為100%; 每一個(gè)子元素display: table-cell; 左右兩側(cè)添加寬度,中間不加寬度
包裹這個(gè)3個(gè)塊的父元素display: flex; 中間的元素flex: 1;
網(wǎng)格布局
/* 網(wǎng)格布局 */
.wrapper {
display: grid;
width: 100%;
grid-template-columns: 300px 1fr 300px;
}
2.2 知道CSS動(dòng)畫的實(shí)現(xiàn)嗎?
[!NOTE]
知道transition 過渡動(dòng)畫和animation 關(guān)鍵幀動(dòng)畫區(qū)別和具體實(shí)現(xiàn)。
1.CSS動(dòng)畫實(shí)現(xiàn)輪播圖
2.CSS動(dòng)畫實(shí)現(xiàn)旋轉(zhuǎn)的硬幣
3.CSS動(dòng)畫實(shí)現(xiàn)鐘擺效果
2.3 CSS盒子模型
2.3.1 說一下CSS的盒子模型?標(biāo)準(zhǔn)模型和IE模型的區(qū)別?CSS如何設(shè)置這兩種模型?
標(biāo)準(zhǔn)盒子模型:width = content
IE盒子模型:width = content + pading + border
box-sizing : content-box
box-sizing : border-box
2.4 CSS樣式獲取
2.4.1 JS如何設(shè)置獲取盒子模型對(duì)應(yīng)的寬度和高度?(面試重點(diǎn))
dom.style.width/height :只能取到內(nèi)聯(lián)樣式的的屬性信息(拿不到外部引入的CSS樣式信息的)
dom.currentStyle.width/height : 會(huì)拿到瀏覽器渲染之后的屬性信息(IE瀏覽器)
window.getComputedStyle(dom).width/height : Chrome/Firefox 兼容, Firefox可以通過document.defaultView.getComputedStyle(dom)的方式來獲取
dom.getBoundingClientRect().width/height : 可以獲取距離viewport位置的寬度和高度
2.5 BFC
2.5.1 根據(jù)盒子模型解釋邊距額重疊問題?邊距重疊問題的解決方案?

父子元素
兄弟元素
其他 --------------------------計(jì)算方式:以參數(shù)的最大值來進(jìn)行計(jì)算
解決方案:對(duì)父級(jí)元素創(chuàng)建BFC
2.5.2 BFC原理
[!NOTE]
BFC:塊級(jí)格式化上下文,IFC(內(nèi)聯(lián)格式化上下文)
在BFC的垂直邊距上面會(huì)發(fā)生重疊
BFC的區(qū)域不會(huì)與浮動(dòng)元素的BOX重疊
BFC在頁面上是一個(gè)獨(dú)立的渲染區(qū)域,外部的元素不會(huì)影響到我,同時(shí)也不會(huì)影響到外部的元素
計(jì)算BFC的高度的時(shí)候,浮動(dòng)元素也會(huì)參與運(yùn)算
2.5.3 如何創(chuàng)建BFC?
float值不是none
position值不是static或者relative
display值為table, table-cell, inline-box1.
overflow : auto/hidden
2.5.4 BFC的使用場(chǎng)景?(重點(diǎn)理解)
解決邊距的重疊問題
<section id="margin">
<style>
#margin {
background-color: #4eff35;
overflow: hidden;
}
#margin>p {
/*上 左右 下*/
margin: 5px auto 25px;
background-color: #ff255f;
}
style>
<p>1p>
<div style="overflow: hidden">
<p>2p>
div>
<p>3p>
section>
BFC 不與float部分重疊的解決
<section id="layout">
<style>
#layout {
background-color: #48adff;
}
#layout .left {
float: left;
height: 300px;
width: 200px;
background-color: #ff4344;
}
#layout .right {
height: 400px;
background-color: #ff255f;
/*給右邊的這個(gè)盒子容器創(chuàng)建一個(gè)BFC, 這個(gè)容器里面的內(nèi)容就會(huì)沿著垂直方向延伸*/
overflow: auto;
/*overflow: auto;*/
/*display: table;*/
/*float: left;*/
/*position: fixed;*/
}
style>
<div class="left">
LEFT
div>
<div class="right">
RIGHT
<p>111p>
<p>111p>
<p>111p>
<p>111p>
<p>111p>
<p>111p>
<p>111p>
<p>111p>
<p>111p>
<p>111p>
<p>111p>
<p>111p>
<p>111p>
<p>111p>
<p>111p>
div>
section>
BFC子元素即使是float元素也要參與運(yùn)算
<section id="float">
<style>
/*一個(gè)盒子內(nèi)部的內(nèi)容如果是浮動(dòng)的話,那么這個(gè)盒子的內(nèi)容實(shí)際上是不參與父容器高度計(jì)算的*/
#float {
background-color: red;
/*overflow: hidden;*/
float: left;
}
#float .float {
float: left;
font-size: 30px;
}
style>
<div class="float">
我是浮動(dòng)的元素
div>
section>
3. 事件相關(guān)
3.1 DOM事件
3.1.1 DOM事件的級(jí)別有哪些?
[!NOTE]
DOM級(jí)別一共可以分為四個(gè)級(jí)別:DOM0級(jí)、DOM1級(jí)、DOM2級(jí)和DOM3級(jí)。而DOM事件分為3個(gè)級(jí)別:DOM0級(jí)事件處理,DOM2級(jí)事件處理和DOM3級(jí)事件處理。
DOM0 : element.onclick = function(e) {}
DOM1 :該標(biāo)準(zhǔn)中未涉及到事件綁定的相關(guān)東西DOM2 : element.addEventListener('click', function(e){}, false), 一個(gè)DOM元素可以添加多個(gè)事件
DOM3 : element.addEventListener('keyup', function(e){}, false),在DOM2標(biāo)準(zhǔn)基礎(chǔ)上面增加了新的事件類型:鼠標(biāo)事件,鍵盤事件,焦點(diǎn)事件
3.1.2 DOM事件模型有哪些?
事件捕獲:從外向內(nèi), window -> document -> body -> button
事件冒泡:從內(nèi)向外,button -> body -> document -> window
3.1.3 DOM事件流?
瀏覽器為當(dāng)前的頁面與用戶進(jìn)行交互的過程中,點(diǎn)擊鼠標(biāo)后事件如何傳入和響應(yīng)的呢?
捕獲階段:從外部容器開始向內(nèi)
目標(biāo)階段:事件通過捕獲到達(dá)目標(biāo)階段
冒泡階段:從目標(biāo)元素再上傳到window對(duì)象
3.1.4 什么事件可以代理?什么事件不可以代理呢?
什么樣的事件可以用事件委托,什么樣的事件不可以用呢?
[!NOTE]
通常支持事件冒泡(Event Bubbling)的事件類型為鼠標(biāo)事件和鍵盤事件,例如:mouseover, mouseout, click, keydown, keypress。
接口事件(指的是那些不一定與用戶操作有關(guān)的事件)則通常不支持事件冒泡(Event Bubbling),例如:load, change, submit, focus, blur。
很明顯:focus 和 blur 都屬于不支持冒泡的接口事件。既然都不支持冒泡,那又如何實(shí)現(xiàn)事件代理呢?
3.1.5 IE和DOM事件流的區(qū)別?
IE采用冒泡型事件 Netscape使用捕獲型事件 DOM使用先捕獲后冒泡型事件
冒泡型事件模型:button -> div -> body (IE瀏覽器本身只支持Bubbling不支持Capturing)
捕獲型事件模型:body -> div-> button (Netscape事件流,網(wǎng)景瀏覽器公司)
DOM事件模型:body -> div -> button -> button -> div -> body (先捕獲后冒泡,除了IE以外的其他瀏覽器都支持標(biāo)準(zhǔn)的DOM事件處理模型)
[!NOTE]
規(guī)范和瀏覽器實(shí)現(xiàn)的差別?
DOM2級(jí)事件規(guī)范的捕獲階段,事件從文檔節(jié)點(diǎn)document開始傳播,現(xiàn)代瀏覽器大多數(shù)都是從window對(duì)象開始傳播事件的;
DOM2級(jí)事件規(guī)范捕獲階段不涉及事件目標(biāo),現(xiàn)代瀏覽器大多數(shù)都在這個(gè)階段包含事件目標(biāo)。
3.1.6 事件對(duì)象event的屬性方法的差別?
IE DOM
cancelBubble = true stopPropagation() // 停止冒泡
returnValue = false preventDefault() // 阻止元素默認(rèn)事件
srcEelement target // 事件目標(biāo)
3.1.7 描述DOM事件捕獲的具體流程?
window -> document -> HTML標(biāo)簽 -> body -> ... -> 目標(biāo)元素
[!NOTE]
關(guān)鍵點(diǎn):注意根節(jié)點(diǎn)是window這個(gè)對(duì)象的
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="container">
<style>
#container {
width: 200px;
height: 200px;
background-color: #ff255f;
}
style>
div>
<script>
// 事件捕獲機(jī)制
window.addEventListener('click', function(){
console.log('window capture');
}, true)
document.addEventListener('click', function () {
console.log('document capture');
}, true)
document.documentElement.addEventListener('click', function () {
console.log('HTML capture');
}, true)
document.body.addEventListener('click', function () {
console.log('body capture');
}, true)
document.getElementById('container').addEventListener('click', function () {
console.log('container capture');
}, true)
// 事件冒泡機(jī)制
window.addEventListener('click', function(){
console.log('window capture');
})
document.addEventListener('click', function () {
console.log('document capture');
})
document.documentElement.addEventListener('click', function () {
console.log('HTML capture');
})
document.body.addEventListener('click', function () {
console.log('body capture');
})
document.getElementById('container').addEventListener('click', function () {
console.log('container capture');
})
// 輸出結(jié)果
window capture --> document capture --> HTML capture --> body capture --> container capture --> container capture --> body capture --> HTML capture --> document capture --> window capture
script>
body>
html>
3.1.8 如何拿到HTML這個(gè)標(biāo)簽節(jié)點(diǎn)元素呢?(加分項(xiàng))
var html = document.documentElement;
3.1.9 描述Event對(duì)象的常見應(yīng)用?
e.preventDefault() : 阻止默認(rèn)事件(如阻止a標(biāo)簽的默認(rèn)跳轉(zhuǎn)行為)
e.stopPropagation() : 阻止事件冒泡的行為
*** e.stopImmediatePropagation() : 事件響應(yīng)的優(yōu)先級(jí)的應(yīng)用場(chǎng)景,如果一個(gè)元素綁定了多個(gè)事件,但是又不想讓其他的事件執(zhí)行的時(shí)候使用該方法【也會(huì)阻止冒泡】
e.currentTarget : 當(dāng)前所綁定的事件對(duì)象
document.documentElement.onclick = function(e) {
console.log(e.currentTarget, e.target); // ...()給綁定事件的那個(gè)元素, 當(dāng)前被點(diǎn)擊的那個(gè)元素
}
[!NOTE]
e.target : 當(dāng)前被點(diǎn)擊的元素,父元素使用事件代理的方式來實(shí)現(xiàn),可以直接使用該屬性獲取被點(diǎn)擊的那個(gè)元素
3.2 如何自定義事件?(重點(diǎn)))
3.2.1 如何給一個(gè)按鈕綁定一個(gè)自己定義的事件呢?
// v1. 使用Event對(duì)象來自定義事件
// 開始創(chuàng)建一個(gè)自己定義的事件對(duì)象
var eve = new Event('customEvent');
// 使用dom2事件處理的方式來給這個(gè)元素綁定一個(gè)事件
var dom = document.documentElement;
dom.addEventListener('customEvent', function(e) {
console.log('customEvent called!');
});
// 下面的這句話可以在適合的場(chǎng)景中來觸發(fā)一個(gè)自己定義的事件對(duì)象
setTimeout(function(){
// 在1s之后觸發(fā)這個(gè)事件
dom.dispatchEvent(eve);
}, 1000)
// v2. 使用CustomEvent來實(shí)現(xiàn)自定義事件
var dom = document.documentElement;
// 使用CustomEvent的方式可以在事件觸發(fā)的時(shí)候傳遞一個(gè)參數(shù),然后通過e.detail 的方式來獲取這個(gè)參數(shù)信息
var myClick = new CustomEvent('myClick', {detail : {name : 'zhangsan', age : 24}});
dom.addEventListener('myClick', function(e){
console.log(e.detail, e.target)
})
dom.dispatchEvent(myClick);
4. HTTP協(xié)議
4.1 HTTP協(xié)議的主要特點(diǎn)?
簡(jiǎn)單快速
靈活
無連接
無狀態(tài)
4.2 HTTP報(bào)文的組成部分?
請(qǐng)求報(bào)文
請(qǐng)求行:請(qǐng)求方法 資源地址 HTTP版本
請(qǐng)求頭:key : value
空行 :
請(qǐng)求體 : name=zhangsan&age=18響應(yīng)報(bào)文 : HTTP版本 狀態(tài)碼
狀態(tài)行
響應(yīng)頭
空行
響應(yīng)體
4.3 HTTP方法?
GET : 獲取資源
POST :傳輸資源
PUT :更新資源
DELETE :刪除資源
HEAD :獲取報(bào)文首部
OPTIONS : 允許客戶端查看服務(wù)器的性能。
4.4 POST和GET的區(qū)別?
GET請(qǐng)求在瀏覽器回退的時(shí)候是無害的,而POST會(huì)再次提交請(qǐng)求
GET請(qǐng)求產(chǎn)生的URL地址可以被收藏,而POST不可以
GET請(qǐng)求會(huì)被瀏覽器主動(dòng)緩存,而POST不會(huì),除非主動(dòng)設(shè)置
GET請(qǐng)求只能進(jìn)行URL編碼,而POST支持多種編碼方式
GET請(qǐng)求參數(shù)會(huì)被完整第保留在瀏覽器的歷史記錄里面,而POST參數(shù)不會(huì)被保留
GET請(qǐng)求愛URL中傳送的參數(shù)的長(zhǎng)度是有限的(2KB),而POST沒有限制
對(duì)參數(shù)的數(shù)據(jù)類型,GET值接受ASCII字符,而POST沒有限制
POST比GET更安全,GET參數(shù)直接暴露在URL上,所以不能用來傳遞敏感信息
9. GET參數(shù)通過URL傳遞,POST參數(shù)直接放在了Request body中
4.5 HTTP狀態(tài)碼?
4.5.1 狀態(tài)碼的第一位
1xx?:指示信息-表示請(qǐng)求已接收,繼續(xù)處理(重點(diǎn))
2xx :成功-表示請(qǐng)求已被成功接收
3xx :重定向-要完成請(qǐng)求必須進(jìn)行更進(jìn)一步的操作
4xx :客戶端錯(cuò)誤-請(qǐng)求有語法錯(cuò)誤或請(qǐng)求無法實(shí)現(xiàn)
5xx :服務(wù)器錯(cuò)誤-服務(wù)器未能實(shí)現(xiàn)合法的請(qǐng)求
4.5.2 狀態(tài)碼詳解
200 OK :客戶端請(qǐng)求成功
206 Partial Content :客戶端發(fā)送了一個(gè)帶有Range頭的GET請(qǐng)求(Video標(biāo)簽或者audio標(biāo)簽在請(qǐng)求數(shù)據(jù)的時(shí)候)
301 Moved Permanently :請(qǐng)求的頁面已經(jīng)轉(zhuǎn)移到了新的URL
302 Found :所請(qǐng)求的頁面已經(jīng)臨時(shí)轉(zhuǎn)移到了新的URL
304 Not Modified :客戶端有緩沖的文檔并發(fā)出了一個(gè)條件下的請(qǐng)求,原來緩沖的文檔還可以繼續(xù)使用
400 Bad Request :客戶端請(qǐng)求有語法錯(cuò)誤,不被服務(wù)器所理解
401 Unauthorized :請(qǐng)求未經(jīng)授權(quán),這個(gè)狀態(tài)碼必須和WWW-Authenticate報(bào)頭域一起使用
403 Forbidden:對(duì)被請(qǐng)求頁面的訪問被禁止
404 Not Found :請(qǐng)求資源不存在
500 Internal Server Error :服務(wù)器發(fā)生不可預(yù)期的錯(cuò)誤,原來緩沖的文檔還可以繼續(xù)使用
503 Service Unavailable :請(qǐng)求未完成,服務(wù)器臨時(shí)過載或宕機(jī),一段時(shí)間后可能恢復(fù)正常
4.6 什么是持久連接?
[!NOTE]
HTTP協(xié)議采用‘請(qǐng)求-應(yīng)答’模式, HTTP1.1版本才支持的,使用Keep-alive字段可以建立一個(gè)長(zhǎng)連接,從而不需要每次請(qǐng)求都去建立一個(gè)新的連接。
4.7 什么是管線化?
4.7.1 基本概念
在使用持久連接(Keep-alive)的情況下,某個(gè)連接上的消息的傳遞類似于:請(qǐng)求1 --> 響應(yīng)1 --> 請(qǐng)求2 --> 響應(yīng)2 --> 請(qǐng)求3 --> 響應(yīng)3
管線化的過程:請(qǐng)求1 --> 請(qǐng)求2 --> 請(qǐng)求3 --> 響應(yīng)1 --> 響應(yīng)2 --> 響應(yīng)3
4.7.2 管線化的特點(diǎn)(特點(diǎn))
管線化機(jī)制通過持久連接完成,僅在HTTP1.1版本之后支持
只有GET和HEAD請(qǐng)求可以進(jìn)行管線化,POST有所限制的
初次創(chuàng)建連接的時(shí)候不應(yīng)該啟動(dòng)管線機(jī)制,因?yàn)閷?duì)方(服務(wù)器)不一定支持HTTP1.1版本的協(xié)議
管線化不會(huì)影響到響應(yīng)到來的順序,HTTP響應(yīng)返回的順序并未改變
HTTP1.1 要求服務(wù)器支持管線化,但并不要求服務(wù)器也對(duì)響應(yīng)進(jìn)行管線化處理,只是要求對(duì)于管線化的請(qǐng)求不失敗即可
由于上面提到的服務(wù)器端問題,開啟管線化很可能并不會(huì)帶來大幅度的性能提升,而且很多服務(wù)器和代理程序?qū)芫€化的支持并不好,因此現(xiàn)代的瀏覽器如Chrome和Firefox默認(rèn)并沒有開啟管線化支持
5. 原型鏈
5.1 創(chuàng)建對(duì)象的幾種方法?
// 1. 使用字面量的方式來創(chuàng)建
var o1 = {name : 'zhangsan'};
var o11 = new Object({name : 'zhangsan'});
// 2. 使用普通構(gòu)造函數(shù)的方式來創(chuàng)建
var M = function(){
this.name = 'zhangsan';
}
var o2 = new M();
// 3. Object.create方法
var p = {name : 'zhangsan'};
var o3 = Object.create(p);
5.2 原型、構(gòu)造函數(shù)、實(shí)例、原型鏈?
構(gòu)造函數(shù):使用new運(yùn)算符來聲明一個(gè)實(shí)例(任何函數(shù)都是可以通過構(gòu)造函數(shù)來使用的)
原型鏈:通過原型鏈可以找到上一級(jí)別的原型對(duì)象
原型對(duì)象:多個(gè)實(shí)例公用的數(shù)據(jù)和屬性或者方法

5.3 instanceof的原理?
[!NOTE]
instanceof 檢測(cè)一個(gè)對(duì)象A是不是另一個(gè)對(duì)象B的實(shí)例的原理是:查看對(duì)象B的prototype指向的對(duì)象是否在對(duì)象A的[[prototype]]鏈上。如果在,則返回true,如果不在則返回false。不過有一個(gè)特殊的情況,當(dāng)對(duì)象B的prototype為null將會(huì)報(bào)錯(cuò)(類似于空指針異常)。
// 2. 使用普通構(gòu)造函數(shù)的方式來創(chuàng)建
var M = function(){
this.name = 'zhangsan';
}
var o2 = new M();
undefined
o2.__proto__ == M.prototype
true
o2.__proto__ == M.prototype
true
o2.__proto__.constructor === Object
false
o2.__proto__.constructor === M
true
5.4 new運(yùn)算符的原理?
一個(gè)新對(duì)象被創(chuàng)建。它繼承于foo.prototype
構(gòu)造函數(shù)foo被執(zhí)行。執(zhí)行的時(shí)候,相應(yīng)的傳參會(huì)被傳入,同時(shí)上下文(this)會(huì)被指定為這個(gè)新實(shí)例,new foo等同于 new foo(),只能用在不傳遞任何參數(shù)的情況
如果構(gòu)造函數(shù)返回了一個(gè)“對(duì)象”,那么這個(gè)對(duì)象會(huì)取代整個(gè)new出來的結(jié)果。如果構(gòu)造函數(shù)沒有返回對(duì)象,那么new 出來的結(jié)果為步驟1創(chuàng)建的對(duì)象
// new 一個(gè)對(duì)象的過程
var _new = function (fn) {
// 1. 創(chuàng)建一個(gè)對(duì)象,這個(gè)對(duì)象要繼承fn這個(gè)構(gòu)造函數(shù)的原型對(duì)象
var o = Object.create(fn.prototype);
// 2. 執(zhí)行構(gòu)造函數(shù)
var k = fn.call(o, arguments);
// 3. 看下執(zhí)行的這個(gè)函數(shù)的運(yùn)行效果是不是函數(shù)
if (typeof k === 'object'){
return k;
}
else
{
return o;
}
}
6. 面向?qū)ο?/h2>6.1 類與繼承:如何實(shí)現(xiàn)繼承,繼承的幾種實(shí)現(xiàn)方式
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<script>
// 類的聲明
function Animal1() {
this.name = 'name';
}
// ES6 中的class的聲明
class Animal2 {
constructor(){
this.name = 'name';
}
}
console.log(new Animal1(), new Animal2());
///////////////////////////////////////////////////////////////////////////////////////////
// 如何實(shí)現(xiàn)類的繼承呢???-----------本質(zhì):原型鏈
// v1. 借助構(gòu)造函數(shù)實(shí)現(xiàn)繼承
function Parent1() {
this.name = 'parent1'
}
Parent1.prototype.sayHello = function () {
console.log('hello');
}
function Child1() {
// 執(zhí)行父親的構(gòu)造函數(shù):
// 1. 實(shí)現(xiàn)原理:將父級(jí)函數(shù)的this指向了這個(gè)子類的實(shí)例上面去了
// 2. 缺點(diǎn):父親的原型鏈上面的方法或者屬性不能被繼承;只能實(shí)現(xiàn)部分繼承
Parent1.call(this);
this.type = 'child1';
}
// 沒有參數(shù)的時(shí)候,可以直接new + 函數(shù)名稱
console.log(res = new Child1);
// v2. 借助原型鏈實(shí)現(xiàn)繼承
function Parent2() {
this.name = 'parent2';
this.data = [1, 2, 3];
}
Parent2.prototype.sayHello = function () {
console.log('hello');
}
function Child2() {
this.type = 'child2';
}
// prototype 就是為了讓這個(gè)對(duì)象的實(shí)例可以訪問到原型鏈上的內(nèi)容
Child2.prototype = new Parent2();
// new Child2().__proto__ === Child2.prototype // true
// new Child2().__proto__.name // parent2
// 原型鏈繼承的缺點(diǎn):
// 1. 原理:通過修改原型鏈來實(shí)現(xiàn)對(duì)象的繼承關(guān)系
// 2. 缺點(diǎn):修改第一個(gè)對(duì)象上面的屬性,會(huì)直接修改第二個(gè)對(duì)象屬性數(shù)據(jù)(引用類型)
var c1 = new Child2();
var c2 = new Child2();
c1.data.push(100, 200, 300);
// v3. 組合繼承
function Parent3() {
this.name = 'parent3';
this.data = [1, 2, 3];
}
function Child3() {
// 1. 借用構(gòu)造函數(shù)繼承
Parent3.call(this);
this.type = 'child3';
}
// 2. 原型鏈繼承
// child3的原型對(duì)象是Parent3的一個(gè)實(shí)例對(duì)象,但是這個(gè)實(shí)例對(duì)象中是沒有constructor這個(gè)屬性的,因此尋找屬性的時(shí)候回沿著這個(gè)實(shí)例對(duì)象的原型鏈繼續(xù)向上尋找new Parent3().prototype 這個(gè)原型對(duì)象的,
// 最終在Parent3.prototype這個(gè)原型對(duì)象中找到了這個(gè)屬性,new一個(gè)對(duì)象找的實(shí)際上是{Parent3.prototype.constructor : Parent3}
Child3.prototype = new Parent3();
var c1 = new Child3();
var c2 = new Child3();
c1.data.push(100, 200, 300);
// 組合繼承的特點(diǎn):
// 1. 原理:結(jié)合借用構(gòu)造函數(shù)繼承和原型鏈繼承的優(yōu)點(diǎn),摒棄二者的缺點(diǎn)
// 2. 缺點(diǎn):父類構(gòu)造函數(shù)在創(chuàng)建實(shí)例的時(shí)候總共執(zhí)行了兩次(new Parent3(), new Child3())
// v4. 組合繼承的優(yōu)化1
function Parent4() {
this.name = 'parent4';
this.data = [1, 2, 3];
}
function Child4() {
// 1. 借用構(gòu)造函數(shù)繼承
Parent4.call(this);
this.type = 'child4';
}
// 讓子類的構(gòu)造函數(shù)的原型對(duì)象和父類構(gòu)造函數(shù)的原型對(duì)象執(zhí)向同一個(gè)對(duì)象(都是同一個(gè)對(duì)象)
Child4.prototype = Parent4.prototype;
// 測(cè)試
var c1 = new Child4();
var c2 = new Child4();
console.log(c1 instanceof Child4, c1 instanceof Parent4);
console.log(c1.constructor) // Parent4? 如何實(shí)現(xiàn):c1.constructor(c1.__proto__.constructor) === Child4 呢?
// 缺點(diǎn):
// 1. 無法通過原型對(duì)象的constructor屬性來獲取對(duì)象的屬性對(duì)應(yīng)的構(gòu)造函數(shù)了(子類和父類公用的是一個(gè)contructor)
// 2. obj instanceof Child4 === true; obj instanceof Parent4 === true
// 3. obj.__proto__.constructor === Child4; obj.__proto__.constructor === Parent4 ???
// v5. 組合繼承的優(yōu)化2【完美寫法】
function Parent5() {
this.name = 'parent5';
this.data = [1, 2, 3, 4, 5];
}
function Child5(){
Parent5.call(this);
this.type = 'child5';
}
// 通過創(chuàng)建中間對(duì)象的方式來把兩個(gè)對(duì)象區(qū)分開
// var obj = new Object(); obj.__proto__ = Constructor.prototype;
// 1. Object.create創(chuàng)建的對(duì)象obj, 這個(gè)obj的原型對(duì)象就是參數(shù)
// 2. Child5的原型對(duì)象是Child5.prototype
// 3. Child5.prototype = obj,obj這個(gè)對(duì)象相當(dāng)于就是一個(gè)中間的橋梁關(guān)系
Child5.prototype = Object.create(Parent5.prototype);
// 當(dāng)前的方式還是會(huì)按照原型鏈一級(jí)一級(jí)向上尋找的, 給Child5的原型對(duì)象上面綁定一個(gè)自己定義的constructor屬性
Child5.prototype.constructor = Child5;
// var s1 = new Child5()
// 上面的代碼等價(jià)于
var obj = Object.create(Parent5.prototype); // obj.prototype = Parent5.prototype
Child5.prototype = obj;
Child5.prototype.constructor = Child5;
// 1. 對(duì)象之間就是通過__proto__ 屬性向上尋找的
// 2. 尋找規(guī)則:child5 ---> Child5.prototype ---> obj(Object.create(Parent5.prototype)) ---> Parent5.prototype
// 技巧:不要讓面試官問太多題目:拖拉時(shí)間【擠牙膏】,把一個(gè)問題盡量吃透
// 消化這一塊內(nèi)容
script>
body>
html>
[!WARNING]
面試技巧
不要讓面試官問太多題目:拖拉時(shí)間【擠牙膏】,把一個(gè)問題盡量吃透
知識(shí)深度
7. 通信
7.1 什么是同源策略個(gè)限制?
[!NOTE]
同源策略限制是從一個(gè)源加載的文檔或腳本如何與來自另一個(gè)源的資源進(jìn)行交互。這是一個(gè)用于隔離潛在惡意文件的關(guān)鍵的安全機(jī)制。(一個(gè)源的文檔或腳本是沒有權(quán)利直接操作另外一個(gè)源的文檔或腳本的)
Cookie, LocalStorage和IndexDB無法讀取
DOM無法獲得;(document.body是無法獲取的)
Ajax請(qǐng)求不能發(fā)送
7.2 前后端如何進(jìn)行通信呢?
Ajax(有同源策略限制);Fetch API則是XMLHttpRequest的最新替代技術(shù), 它是W3C的正式標(biāo)準(zhǔn)
WebSocket:支持跨域請(qǐng)求數(shù)據(jù),沒有同源策略的限制
CORS:新的協(xié)議通信標(biāo)準(zhǔn);CORS則將導(dǎo)致跨域訪問的請(qǐng)求分為三種:Simple Request,Preflighted Request以及Requests with Credential;cors相對(duì)于jsonp而言的好處就是支持所有的請(qǐng)求方式,不止是get請(qǐng)求,還支持post,put請(qǐng)求等等,而它的缺點(diǎn)就很明顯,無法兼容所有的瀏覽器,對(duì)于要兼容到老式瀏覽器而言,還是使用jsonp好點(diǎn)
7.3 如何創(chuàng)建Ajax呢?
XMLHttpRequest對(duì)象的工作流程
瀏覽器的兼容性處理【重點(diǎn)】
事件的觸發(fā)條件
事件的觸發(fā)順序
function ajax(params){
// 1. 創(chuàng)建對(duì)象,考慮兼容性【重點(diǎn)】
var xhr = XMLHTTPRequest ? new XMLHTTPRequest() : new window.ActiveXObject('Microsoft.XMLHTTP'); // *** 兼容性問題必須考慮
// 2. 打開連接
var type = params.type || 'GET',
url = params.url || '',
data = params.data || {},
success = params.success,
error = params.error,
dataArr = [];
for (var k in data) {
dataArr.push(k + '=' + data[k]);
}
//帶上Cookie
xhr.withCredentials = true;
if (type.toUpperCase() === 'GET') {
// get
url += '?' + dataArr.join('&');
// 問號(hào)結(jié)尾的話,直接替換為空字符串
xhr.open(type, url.replace(/\?$/g, ''), true);
// GET 請(qǐng)求的話,是不需要再send方法中帶上參數(shù)的
xhr.send();
}
else {
// POST
xhr.open(type, url, true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
// POST 請(qǐng)求需要把數(shù)據(jù)放在send方法里面, data = name=zhangsna&age=18&sex=male
xhr.send(dataArr.join('&'));
}
// 開始監(jiān)聽變化
xhr.onreadystatechange = function(){
// 這里需要考慮強(qiáng)緩存和協(xié)商緩存的話直接處理,206是媒體資源的創(chuàng)建方式
if (xhr.readyState === 4 && xhr.status === 200 || xhr.status === 304) {
var res;
if (success instanceof Function) {
res = xhr.responseText;
if (typeof res === 'string') {
res = JSON.parse(res);
// 開始執(zhí)行成功的回調(diào)函數(shù)
success.call(xhr, res);
}
} else {
if (error instanceof Function) {
// 失敗的話直接返回這個(gè)responseText中的內(nèi)容信息
error.call(xhr, res);
}
}
}
}
}
7.4 跨域通信的幾種方式?
7.4.1 JSONP
function jsonp(url, onsuccess, onerror, charset){
// 1. 全局注冊(cè)一個(gè)callback
var callbackName = 'callback' + Math.random() * 100;
window[callbackName] = function(){
if (onsuccess && typeof onsuccess === 'Function') {
onsuccess(arguments[0]);
}
}
// 2. 動(dòng)態(tài)創(chuàng)建一個(gè)script標(biāo)簽
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
charset && script.setAttribute('charset', charset);
script.setAttribute('src', url);
script.async = true;
// 3. 開始監(jiān)聽處理的過程
script.onload = script.onreadystatechange = function(){
if (!script.readyState || /loaded|complete/.test(script.readyState)) {
// 4. 成功之后移除這個(gè)事件
script.onload = script.onreadystatechange = null;
// 刪除這個(gè)script的DOM對(duì)象(head.removeChild(script), 這個(gè)DOM節(jié)點(diǎn)的父節(jié)點(diǎn)相當(dāng)于是head標(biāo)簽這個(gè)父節(jié)點(diǎn))
script.parentNode && script.parentNode.removeChild(script);
// 刪除函數(shù)或變量
window[callbackName] = null;
}
}
script.onerror = function(){
if (onerror && typeof onerror === 'Function') {
onerror();
}
}
// 5. 開始發(fā)送這個(gè)請(qǐng)求(把這個(gè)標(biāo)簽放在頁面中的head標(biāo)簽中即可)
document.getElementsByTagName('head')[0].appendChild(script);
}
7.4.2 Hash
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<script>
// 類的聲明
function Animal1() {
this.name = 'name';
}
// ES6 中的class的聲明
class Animal2 {
constructor(){
this.name = 'name';
}
}
console.log(new Animal1(), new Animal2());
///////////////////////////////////////////////////////////////////////////////////////////
// 如何實(shí)現(xiàn)類的繼承呢???-----------本質(zhì):原型鏈
// v1. 借助構(gòu)造函數(shù)實(shí)現(xiàn)繼承
function Parent1() {
this.name = 'parent1'
}
Parent1.prototype.sayHello = function () {
console.log('hello');
}
function Child1() {
// 執(zhí)行父親的構(gòu)造函數(shù):
// 1. 實(shí)現(xiàn)原理:將父級(jí)函數(shù)的this指向了這個(gè)子類的實(shí)例上面去了
// 2. 缺點(diǎn):父親的原型鏈上面的方法或者屬性不能被繼承;只能實(shí)現(xiàn)部分繼承
Parent1.call(this);
this.type = 'child1';
}
// 沒有參數(shù)的時(shí)候,可以直接new + 函數(shù)名稱
console.log(res = new Child1);
// v2. 借助原型鏈實(shí)現(xiàn)繼承
function Parent2() {
this.name = 'parent2';
this.data = [1, 2, 3];
}
Parent2.prototype.sayHello = function () {
console.log('hello');
}
function Child2() {
this.type = 'child2';
}
// prototype 就是為了讓這個(gè)對(duì)象的實(shí)例可以訪問到原型鏈上的內(nèi)容
Child2.prototype = new Parent2();
// new Child2().__proto__ === Child2.prototype // true
// new Child2().__proto__.name // parent2
// 原型鏈繼承的缺點(diǎn):
// 1. 原理:通過修改原型鏈來實(shí)現(xiàn)對(duì)象的繼承關(guān)系
// 2. 缺點(diǎn):修改第一個(gè)對(duì)象上面的屬性,會(huì)直接修改第二個(gè)對(duì)象屬性數(shù)據(jù)(引用類型)
var c1 = new Child2();
var c2 = new Child2();
c1.data.push(100, 200, 300);
// v3. 組合繼承
function Parent3() {
this.name = 'parent3';
this.data = [1, 2, 3];
}
function Child3() {
// 1. 借用構(gòu)造函數(shù)繼承
Parent3.call(this);
this.type = 'child3';
}
// 2. 原型鏈繼承
// child3的原型對(duì)象是Parent3的一個(gè)實(shí)例對(duì)象,但是這個(gè)實(shí)例對(duì)象中是沒有constructor這個(gè)屬性的,因此尋找屬性的時(shí)候回沿著這個(gè)實(shí)例對(duì)象的原型鏈繼續(xù)向上尋找new Parent3().prototype 這個(gè)原型對(duì)象的,
// 最終在Parent3.prototype這個(gè)原型對(duì)象中找到了這個(gè)屬性,new一個(gè)對(duì)象找的實(shí)際上是{Parent3.prototype.constructor : Parent3}
Child3.prototype = new Parent3();
var c1 = new Child3();
var c2 = new Child3();
c1.data.push(100, 200, 300);
// 組合繼承的特點(diǎn):
// 1. 原理:結(jié)合借用構(gòu)造函數(shù)繼承和原型鏈繼承的優(yōu)點(diǎn),摒棄二者的缺點(diǎn)
// 2. 缺點(diǎn):父類構(gòu)造函數(shù)在創(chuàng)建實(shí)例的時(shí)候總共執(zhí)行了兩次(new Parent3(), new Child3())
// v4. 組合繼承的優(yōu)化1
function Parent4() {
this.name = 'parent4';
this.data = [1, 2, 3];
}
function Child4() {
// 1. 借用構(gòu)造函數(shù)繼承
Parent4.call(this);
this.type = 'child4';
}
// 讓子類的構(gòu)造函數(shù)的原型對(duì)象和父類構(gòu)造函數(shù)的原型對(duì)象執(zhí)向同一個(gè)對(duì)象(都是同一個(gè)對(duì)象)
Child4.prototype = Parent4.prototype;
// 測(cè)試
var c1 = new Child4();
var c2 = new Child4();
console.log(c1 instanceof Child4, c1 instanceof Parent4);
console.log(c1.constructor) // Parent4? 如何實(shí)現(xiàn):c1.constructor(c1.__proto__.constructor) === Child4 呢?
// 缺點(diǎn):
// 1. 無法通過原型對(duì)象的constructor屬性來獲取對(duì)象的屬性對(duì)應(yīng)的構(gòu)造函數(shù)了(子類和父類公用的是一個(gè)contructor)
// 2. obj instanceof Child4 === true; obj instanceof Parent4 === true
// 3. obj.__proto__.constructor === Child4; obj.__proto__.constructor === Parent4 ???
// v5. 組合繼承的優(yōu)化2【完美寫法】
function Parent5() {
this.name = 'parent5';
this.data = [1, 2, 3, 4, 5];
}
function Child5(){
Parent5.call(this);
this.type = 'child5';
}
// 通過創(chuàng)建中間對(duì)象的方式來把兩個(gè)對(duì)象區(qū)分開
// var obj = new Object(); obj.__proto__ = Constructor.prototype;
// 1. Object.create創(chuàng)建的對(duì)象obj, 這個(gè)obj的原型對(duì)象就是參數(shù)
// 2. Child5的原型對(duì)象是Child5.prototype
// 3. Child5.prototype = obj,obj這個(gè)對(duì)象相當(dāng)于就是一個(gè)中間的橋梁關(guān)系
Child5.prototype = Object.create(Parent5.prototype);
// 當(dāng)前的方式還是會(huì)按照原型鏈一級(jí)一級(jí)向上尋找的, 給Child5的原型對(duì)象上面綁定一個(gè)自己定義的constructor屬性
Child5.prototype.constructor = Child5;
// var s1 = new Child5()
// 上面的代碼等價(jià)于
var obj = Object.create(Parent5.prototype); // obj.prototype = Parent5.prototype
Child5.prototype = obj;
Child5.prototype.constructor = Child5;
// 1. 對(duì)象之間就是通過__proto__ 屬性向上尋找的
// 2. 尋找規(guī)則:child5 ---> Child5.prototype ---> obj(Object.create(Parent5.prototype)) ---> Parent5.prototype
// 技巧:不要讓面試官問太多題目:拖拉時(shí)間【擠牙膏】,把一個(gè)問題盡量吃透
// 消化這一塊內(nèi)容
script>
body>
html>
[!WARNING]
面試技巧
不要讓面試官問太多題目:拖拉時(shí)間【擠牙膏】,把一個(gè)問題盡量吃透
知識(shí)深度
[!NOTE]
同源策略限制是從一個(gè)源加載的文檔或腳本如何與來自另一個(gè)源的資源進(jìn)行交互。這是一個(gè)用于隔離潛在惡意文件的關(guān)鍵的安全機(jī)制。(一個(gè)源的文檔或腳本是沒有權(quán)利直接操作另外一個(gè)源的文檔或腳本的)
Cookie, LocalStorage和IndexDB無法讀取
DOM無法獲得;(document.body是無法獲取的)
Ajax請(qǐng)求不能發(fā)送
Ajax(有同源策略限制);Fetch API則是XMLHttpRequest的最新替代技術(shù), 它是W3C的正式標(biāo)準(zhǔn)
WebSocket:支持跨域請(qǐng)求數(shù)據(jù),沒有同源策略的限制
CORS:新的協(xié)議通信標(biāo)準(zhǔn);CORS則將導(dǎo)致跨域訪問的請(qǐng)求分為三種:Simple Request,Preflighted Request以及Requests with Credential;cors相對(duì)于jsonp而言的好處就是支持所有的請(qǐng)求方式,不止是get請(qǐng)求,還支持post,put請(qǐng)求等等,而它的缺點(diǎn)就很明顯,無法兼容所有的瀏覽器,對(duì)于要兼容到老式瀏覽器而言,還是使用jsonp好點(diǎn)
XMLHttpRequest對(duì)象的工作流程
瀏覽器的兼容性處理【重點(diǎn)】
事件的觸發(fā)條件
事件的觸發(fā)順序
function ajax(params){
// 1. 創(chuàng)建對(duì)象,考慮兼容性【重點(diǎn)】
var xhr = XMLHTTPRequest ? new XMLHTTPRequest() : new window.ActiveXObject('Microsoft.XMLHTTP'); // *** 兼容性問題必須考慮
// 2. 打開連接
var type = params.type || 'GET',
url = params.url || '',
data = params.data || {},
success = params.success,
error = params.error,
dataArr = [];
for (var k in data) {
dataArr.push(k + '=' + data[k]);
}
//帶上Cookie
xhr.withCredentials = true;
if (type.toUpperCase() === 'GET') {
// get
url += '?' + dataArr.join('&');
// 問號(hào)結(jié)尾的話,直接替換為空字符串
xhr.open(type, url.replace(/\?$/g, ''), true);
// GET 請(qǐng)求的話,是不需要再send方法中帶上參數(shù)的
xhr.send();
}
else {
// POST
xhr.open(type, url, true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
// POST 請(qǐng)求需要把數(shù)據(jù)放在send方法里面, data = name=zhangsna&age=18&sex=male
xhr.send(dataArr.join('&'));
}
// 開始監(jiān)聽變化
xhr.onreadystatechange = function(){
// 這里需要考慮強(qiáng)緩存和協(xié)商緩存的話直接處理,206是媒體資源的創(chuàng)建方式
if (xhr.readyState === 4 && xhr.status === 200 || xhr.status === 304) {
var res;
if (success instanceof Function) {
res = xhr.responseText;
if (typeof res === 'string') {
res = JSON.parse(res);
// 開始執(zhí)行成功的回調(diào)函數(shù)
success.call(xhr, res);
}
} else {
if (error instanceof Function) {
// 失敗的話直接返回這個(gè)responseText中的內(nèi)容信息
error.call(xhr, res);
}
}
}
}
}
function jsonp(url, onsuccess, onerror, charset){
// 1. 全局注冊(cè)一個(gè)callback
var callbackName = 'callback' + Math.random() * 100;
window[callbackName] = function(){
if (onsuccess && typeof onsuccess === 'Function') {
onsuccess(arguments[0]);
}
}
// 2. 動(dòng)態(tài)創(chuàng)建一個(gè)script標(biāo)簽
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
charset && script.setAttribute('charset', charset);
script.setAttribute('src', url);
script.async = true;
// 3. 開始監(jiān)聽處理的過程
script.onload = script.onreadystatechange = function(){
if (!script.readyState || /loaded|complete/.test(script.readyState)) {
// 4. 成功之后移除這個(gè)事件
script.onload = script.onreadystatechange = null;
// 刪除這個(gè)script的DOM對(duì)象(head.removeChild(script), 這個(gè)DOM節(jié)點(diǎn)的父節(jié)點(diǎn)相當(dāng)于是head標(biāo)簽這個(gè)父節(jié)點(diǎn))
script.parentNode && script.parentNode.removeChild(script);
// 刪除函數(shù)或變量
window[callbackName] = null;
}
}
script.onerror = function(){
if (onerror && typeof onerror === 'Function') {
onerror();
}
}
// 5. 開始發(fā)送這個(gè)請(qǐng)求(把這個(gè)標(biāo)簽放在頁面中的head標(biāo)簽中即可)
document.getElementsByTagName('head')[0].appendChild(script);
}
hash 改變后頁面不會(huì)刷新的
[!NOTE]
使用場(chǎng)景:當(dāng)前的頁面A通過iframe或者frame嵌入了跨域的頁面
// 1. A頁面中的代碼如下
var B = document.getElementsByTagName('iframe');
B.src = B.src + '#' + JSON.stringfy(data);
// 2. B中的偽代碼如下
window.onhashchange = function(){
var data = window.location.hash; // 接受數(shù)據(jù)
data = JSON.parse(data);
}
7.4.3 postMessage(HTML5中新增)
[!NOTE]
使用場(chǎng)景:可以實(shí)現(xiàn)窗口A(A.com)向窗口B(B.com)發(fā)送信息
// 1. 窗口B中的代碼如下
var BWindow = window;
BWindow.postMessage(JSON.stringfy(data), 'http://www.A.com');
// 2. 窗口A中代碼
var AWindow = window;
AWindow.addEventListener('message', function(e){
console.log(e.origin); // http://www.B.com
console.log(e.source); // BWindow
e.source.postMessage('已成功收到消息');
console.log(JSON.parse(e.data)); // data
}, false)
// 父窗口給子窗口發(fā)信息,需要用iframe的contentWindow屬性作為調(diào)用主體
// 子窗口給父窗口發(fā)的信息需要使用window.top,多層iframe使用window.frameElement
7.4.4 . WebSocket
[!NOTE]
不受同源策略影響,可以直接使用
var ws = new window.WebSocket('ws://echo.websocket.org');
// 打開連接
ws.onopen = function(e){
console.log('Connection open ……');
ws.send('Hello WebSocket!');
}
// 接受消息
ws.onmessage = function(e){
console.log('Received Message : ', e.data);
}
// 關(guān)閉連接
ws.onclose = function(e){
console.log('Connection closed');
}
7.4.5 CORS
支持跨域通信版本的Ajax,是一種新的標(biāo)準(zhǔn)(Origin頭)【ajax的一個(gè)變種,適用于任何】
http://www.ruanyifeng.com/blog/2016/04/cors.html
fetch('/get/name', {
method : 'get'
}).then(function(response){
console.log(response);
}).catch(function(err){
// 出錯(cuò)了;等價(jià)于then的第二個(gè)參數(shù)
});
// 原因:瀏覽器默認(rèn)會(huì)攔截ajax請(qǐng)求,會(huì)根據(jù)頭中的origin消息進(jìn)行判斷處理消息;Origin字段用來說明,本次請(qǐng)求來自哪個(gè)源(協(xié)議 + 域名 + 端口)。服務(wù)器根據(jù)這個(gè)值,決定是否同意這次請(qǐng)求。JSONP只支持GET請(qǐng)求,CORS支持所有類型的HTTP請(qǐng)求。JSONP的優(yōu)勢(shì)在于支持老式瀏覽器,以及可以向不支持CORS的網(wǎng)站請(qǐng)求數(shù)據(jù)。
7.4.5.1 CORS請(qǐng)求的基本流程
對(duì)于簡(jiǎn)單請(qǐng)求,瀏覽器直接發(fā)出CORS請(qǐng)求。具體來說,就是在頭信息之中,增加一個(gè)Origin字段。
Origin字段用來說明,本次請(qǐng)求來自哪個(gè)源(協(xié)議 + 域名 + 端口)。服務(wù)器根據(jù)這個(gè)值,決定是否同意這次請(qǐng)求。
如果Origin指定的源,不在許可范圍內(nèi),服務(wù)器會(huì)返回一個(gè)正常的HTTP回應(yīng)。瀏覽器發(fā)現(xiàn),這個(gè)回應(yīng)的頭信息沒有包含Access-Control-Allow-Origin字段(詳見下文),就知道出錯(cuò)了,從而拋出一個(gè)錯(cuò)誤,被XMLHttpRequest的onerror回調(diào)函數(shù)捕獲。
如果Origin指定的域名在許可范圍內(nèi),服務(wù)器返回的響應(yīng),會(huì)多出幾個(gè)頭信息字段。
Access-Control-Allow-Origin: http://api.bob.com // 必需的字段
Access-Control-Allow-Credentials: true // 可選字段: 是否允許發(fā)送cookie
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
簡(jiǎn)單請(qǐng)求的CORS請(qǐng)求,會(huì)在正式通信之前,增加一次HTTP查詢請(qǐng)求,稱為"預(yù)檢"請(qǐng)求(preflight)。OPTIONS表示當(dāng)前的這個(gè)請(qǐng)求是用來詢問的;服務(wù)器收到"預(yù)檢"請(qǐng)求以后,檢查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,確認(rèn)允許跨源請(qǐng)求,就可以做出回應(yīng)。
7.4.5.2 JSONP和CORS的區(qū)別?
JSONP只支持GET請(qǐng)求,CORS支持所有類型的HTTP請(qǐng)求
JSONP的優(yōu)勢(shì)在于支持老式瀏覽器,以及可以向不支持CORS的網(wǎng)站請(qǐng)求數(shù)據(jù)。
8. 安全
8.1 CSRF
8.1.1 基本概念和縮寫
CSRF:跨站請(qǐng)求偽造,Cross site request forgery
8.1.2 CSRF 攻擊原理

8.1.3 可以成功攻擊的條件?
目標(biāo)網(wǎng)站存在CSRF漏洞的請(qǐng)求接口(一般為get請(qǐng)求)
目標(biāo)用戶之前已經(jīng)成功登錄過這個(gè)網(wǎng)站(留下了Cookie)
8.1.4 如何防御呢?
Token驗(yàn)證:訪問服務(wù)器接口的時(shí)候,會(huì)自動(dòng)帶上這個(gè)token
Referer驗(yàn)證:驗(yàn)證網(wǎng)站的頁面來源(只有我當(dāng)前網(wǎng)站下的頁面才可以請(qǐng)求,對(duì)于來自其他網(wǎng)站的請(qǐng)求一律攔截)
隱藏令牌:隱藏信息會(huì)放在header中(類似于Token)
8.2 XSS
8.2.1 基本概念和縮寫
XSS:cross-site scripting, 跨站腳本攻擊
8.2.2 XSS防御
攻擊原理: 注入JS腳本
防御措施: 讓JS代碼無法解析執(zhí)行
8.3 CSRF和XSS的區(qū)別呢?
CSRF:網(wǎng)站本身存在漏洞的接口,依賴這些登錄過目標(biāo)網(wǎng)站的用戶來實(shí)現(xiàn)信息的竊取;
XSS:向頁面中注入JS執(zhí)行,JS函數(shù)體內(nèi)執(zhí)行目標(biāo)任務(wù);
[!NOTE]
一定要說出中文名稱,實(shí)現(xiàn)原理,防范措施都說出來
不要拖泥帶水,言簡(jiǎn)意賅
9. 算法
[!NOTE]
算法攻略:多刷題才是硬道理!!!
二三面(知識(shí)深度面)
10. 渲染機(jī)制
10.1 什么是DOCTYPE及作用?
DTD(Document Type Definition):文檔類型定義,是一系列的語法規(guī)則,用來定義XML或者(X)HTML的文件類型。瀏覽器會(huì)使用它來判斷文檔的類型,決定使用哪一種協(xié)議來解析,以及切換瀏覽器模式;
DOCTYPE:是用來聲明文檔類型和DTD規(guī)范的,一個(gè)主要的用途是文件的合法性驗(yàn)證;如果文件代碼不合法,那么瀏覽器解析的時(shí)候就會(huì)出現(xiàn)一些出錯(cuò)
總結(jié):Doctype就是通知瀏覽器當(dāng)前的文檔是屬于那種類型的,包含哪些DTD。
<DOCTYPE html>
<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd" >
<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " http://www.w3.org/TR/html4/loose.dtd" >
[!NOTE]
在W3C標(biāo)準(zhǔn)出來之前,不同的瀏覽器對(duì)頁面渲染有不同的標(biāo)準(zhǔn),產(chǎn)生了一定的差異。這種渲染方式叫做混雜模式。在W3C標(biāo)準(zhǔn)出來之后,瀏覽器對(duì)頁面的渲染有了統(tǒng)一的標(biāo)準(zhǔn),這種渲染方式叫做標(biāo)準(zhǔn)模式。不存在或者形式不正確會(huì)導(dǎo)致HTML或XHTML文檔以混雜模式呈現(xiàn),就是把如何渲染html頁面的權(quán)利交給了瀏覽器,有多少種瀏覽器就有多少種展示方式。因此要提高瀏覽器兼容性就必須重視
10.2 嚴(yán)格模式和混雜模式
[!NOTE]
嚴(yán)格模式和混雜模式都是瀏覽器的呈現(xiàn)模式,瀏覽器究竟使用混雜模式還是嚴(yán)格模式呈現(xiàn)頁面與網(wǎng)頁中的DTD(文件類型定義)有關(guān),DTD里面包含了文檔的規(guī)則。比如:loose.dtd
嚴(yán)格模式:又稱標(biāo)準(zhǔn)模式,是指瀏覽器按照W3C標(biāo)準(zhǔn)來解析代碼,呈現(xiàn)頁面
混雜模式:又稱為怪異模式或者兼容模式,是指瀏覽器按照自己的方式來解析代碼,使用一種比較寬松的向后兼容的方式來顯示頁面。
10.3 瀏覽器的渲染過程?

10.3.1 開始進(jìn)行DOM解析,渲染DOM Tree

10.3.2 開始進(jìn)行CSS解析,渲染CSSOM Tree

10.3.3 DOM樹和CSS樹的結(jié)合,最后會(huì)轉(zhuǎn)換為Render Tree

10.3.4 Layout的過程,計(jì)算每一個(gè)DOM元素的位置、寬度、高度等信息,最終渲染并顯示頁面到瀏覽器

10.4 何時(shí)會(huì)觸發(fā)Reflow?
[!NOTE]
定義:DOM結(jié)構(gòu)中每個(gè)元素都有自己的盒子模型,這些都是需要根據(jù)各種樣式來計(jì)算并根據(jù)計(jì)算結(jié)果將元素放在它該出現(xiàn)的位置,這個(gè)過程就是reflow;
當(dāng)你增加、刪除、修改DOM節(jié)點(diǎn)的時(shí)候,會(huì)導(dǎo)致Reflow或Repaint
當(dāng)你移動(dòng)DOM的位置,或者設(shè)置動(dòng)畫的時(shí)候
當(dāng)你修改CSS樣式的時(shí)候
當(dāng)你Resize窗口的時(shí)候(移動(dòng)端沒有這個(gè)問題,與瀏覽器有關(guān)),或者在滾動(dòng)窗口的時(shí)候
當(dāng)你修改網(wǎng)頁的默認(rèn)的字體的時(shí)候
10.5 何時(shí)回觸發(fā)Repaint?
[!NOTE]
定義:當(dāng)各種盒子的位置、大小以及其他屬性,例如顏色、字體大小都確定下來以后,瀏覽器于是便按照元素各自的特性繪制了一遍,于是頁面的內(nèi)容出現(xiàn)了,這個(gè)過程就是repaint
DOM改動(dòng)
CSS改動(dòng)
10.6 如何最大程度上的減少瀏覽器的重繪Repaint過程(頻率)呢?
10.6.1 避免在document上直接進(jìn)行頻繁的DOM操作,如果確實(shí)需要可以采用off-document的方式進(jìn)行
先將元素從document中刪除,完成修改之后然后再把元素放回原來的位置
將元素的display設(shè)置為none, 然后完成修改之后再把元素的display屬性修改為原來的值
如果需要?jiǎng)?chuàng)建多個(gè)DOM節(jié)點(diǎn),可以使用DocumentFragment創(chuàng)建完畢之后一次性地加入document中去
var frag = document.createDocumentFragment();
frag.appendChild(dom); /*每次創(chuàng)建的節(jié)點(diǎn)先放入DocumentFragment中*/
10.6.2 集中修改樣式
盡可能少的修改元素style上的屬性
盡量通過修改className來修改樣式(一次性修改)
通過cssText屬性來設(shè)置樣式值
document.getElementById("d1").style.cssText = "color:red; font-size:13px;";
10.6.3 緩存Layout的屬性值
[!NOTE]
對(duì)于Layout屬性中非引用類型的值(數(shù)字型),如果需要多次訪問則可以在一次訪問時(shí)先存儲(chǔ)到局部變量中,之后都使用局部變量,這樣可以避免每次讀取屬性時(shí)造成瀏覽器的渲染。
var width = el.offsetWidth;
var scrollLeft = el.scrollLeft;
10.6.4 設(shè)置元素的position為absolute或fixed
[!NOTE]
在元素的position為static和relative時(shí),元素處于DOM樹結(jié)構(gòu)當(dāng)中,當(dāng)對(duì)元素的某個(gè)操作需要重新渲染時(shí),瀏覽器會(huì)渲染整個(gè)頁面。將元素的position設(shè)置為absolute和fixed可以使元素從DOM樹結(jié)構(gòu)中脫離出來獨(dú)立的存在,而瀏覽器在需要渲染時(shí)只需要渲染該元素以及位于該元素下方的元素,從而在某種程度上縮短瀏覽器渲染時(shí)間。
11. 布局Layout?
Layout屬性包括:
offsetLeft、offsetTop、offsetHeight、offsetWidth: 相對(duì)于父對(duì)象的邊距信息,且返回值為數(shù)字;left獲取或設(shè)置相對(duì)于具有定位屬性(position定義為relative)的父對(duì)象的邊距信息,返回值為字符串10px
scrollTop/Left/Width/Height:滾動(dòng)條在各個(gè)方向上拉動(dòng)的距離,返回值為數(shù)字
clientTop/Left/Width/Height:瀏覽器的可視區(qū)域的大小
getComputedStyle()、currentStyle(in IE):瀏覽器渲染DOM元素之后的寬度和高度等樣式信息
12. JS運(yùn)行機(jī)制
12.1 如何理解JS的單線程?
看代碼,寫結(jié)果?
// 同步任務(wù)
console.log(1);
// 異步任務(wù)要掛起
setTimeout(function(){
console.log(2)
}, 0);
console.log(3)
// out : 1 3 2
console.log('A');
setTimeout(function(){
console.log('B')
}, 0);
while (true) {
}
// out : A
12.2 什么是任務(wù)隊(duì)列?
for (var i = 0; i < 4; i++) {
// setTimeout , setInterval 只有在時(shí)間到了的時(shí)候,才會(huì)把這個(gè)事件放在異步隊(duì)列中去
setTimeout(function(){
console.log(i);
}, 1000);
}
// out : 4 4 4 4
12.3 什么是Event Loop?
[!NOTE]
JS是單線程的,瀏覽器引擎會(huì)先來執(zhí)行同步任務(wù),遇到異步任務(wù)之后,會(huì)把當(dāng)前的這個(gè)異步任務(wù)放在time模塊中,等到主線程中的所有的同步任務(wù)全部執(zhí)行完畢之后;然后當(dāng)前的這個(gè)異步任務(wù)只有時(shí)間到了之后,才會(huì)把這個(gè)任務(wù)(回調(diào)函數(shù))放在一個(gè)異步隊(duì)列中;當(dāng)當(dāng)前的任務(wù)棧中的任務(wù)全部執(zhí)行完畢了之后,會(huì)先去執(zhí)行微任務(wù)隊(duì)列中的任務(wù)(Promise),然后等到微任務(wù)隊(duì)列中的所有任務(wù)全部執(zhí)行完畢之后,再去執(zhí)行process.nextTick()這個(gè)函數(shù),等到這個(gè)函數(shù)執(zhí)行完畢之后,本次的事件輪訓(xùn)結(jié)束;
開啟新的執(zhí)行棧,從宏任務(wù)隊(duì)列中依次取出異步任務(wù),開始執(zhí)行;每個(gè)宏任務(wù)執(zhí)行都會(huì)重新開啟一個(gè)新的任務(wù)執(zhí)行棧
12.3.1 3個(gè)關(guān)鍵點(diǎn)
執(zhí)行棧執(zhí)行的是同步任務(wù);
什么時(shí)候去異步隊(duì)列中取這個(gè)任務(wù);
什么時(shí)候向這個(gè)任務(wù)隊(duì)列中放入新的異步任務(wù)
12.3.2 異步任務(wù)的分類
setTimeout, setInterval;
DOM事件(點(diǎn)擊按鈕的時(shí)候也會(huì)先去執(zhí)行同步任務(wù));
Promise
13. 知識(shí)點(diǎn)總結(jié)
理解JS的單線程的概念
理解任務(wù)隊(duì)列
理解Event Loop
理解哪些語句會(huì)翻入到異步任務(wù)隊(duì)列
理解與放入到異步任務(wù)隊(duì)列的時(shí)機(jī)
13.1 頁面性能
13.1.1 提升頁面性能的方法有哪些?
資源壓縮合并,減少HTTP請(qǐng)求;
非核心代碼的異步加載 ---> 異步加載的方式有哪些?---> 異步加載的區(qū)別?
利用瀏覽器的緩存 ---> 緩存的分類 ---> 緩存的原理
使用CDN加速
預(yù)解析DNS:DNS Prefetch 是一種DNS 預(yù)解析技術(shù),當(dāng)你瀏覽網(wǎng)頁時(shí),瀏覽器會(huì)在加載網(wǎng)頁時(shí)對(duì)網(wǎng)頁中的域名進(jìn)行解析緩存,這樣在你單擊當(dāng)前網(wǎng)頁中的連接時(shí)就無需進(jìn)行DNS的解析,減少用戶等待時(shí)間,提高用戶體驗(yàn)。(提前解析域名,而不是點(diǎn)擊鏈接的時(shí)候才去進(jìn)行DNS域名解析,可以節(jié)省DNS解析需要耗費(fèi)的20-120毫秒時(shí)間)
<meta http-equiv="x-dns-prefetch-control" content="on">
<link rel="dns-prefetch" href="http://www.zhix.net">
<link rel="dns-prefetch" href="http://bdimg.share.baidu.com" />
<link rel="dns-prefetch" href="http://nsclick.baidu.com" />
<link rel="dns-prefetch" href="http://#" />
<link rel="dns-prefetch" href="http://eiv.baidu.com" />
14. 異步加載的方式
14.1 動(dòng)態(tài)腳本的加載
var script = document.createElement('script');
document.getElementsByTagName('head')[0].appendChild(script);
// 沒有 defer 或 async,瀏覽器會(huì)立即加載并執(zhí)行指定的腳本,“立即”指的是在渲染該 script 標(biāo)簽之下的文檔元素之前,也就是說不等待后續(xù)載入的文檔元素,讀到就加載并執(zhí)行。
<script src="script.js">script>
14.2 defer
<script defer src="myscript.js">script>
14.3 async
<script async src="script.js">script>
14.4 異步加載的區(qū)別?
[!NOTE]
defer是在HTML解析完成之后(DOMContentLoaded事件執(zhí)行之后)才會(huì)執(zhí)行,如果是多個(gè),會(huì)按照加載的順序依次執(zhí)行(按照順序執(zhí)行)
async是在加載完之后立即執(zhí)行,如果是多個(gè),執(zhí)行順序和加載順序無關(guān)(與順序無關(guān))
15. 說一下瀏覽器的緩存機(jī)制吧?
15.1 緩存的分類
[!NOTE]
緩存目的就是為了提升頁面的性能
15.1.1 強(qiáng)緩存
直接從本地讀取,不發(fā)送請(qǐng)求
Response Headers
cache-control: max-age=315360000(相對(duì)時(shí)間,優(yōu)先級(jí)比expires高)
expires: Sat, 10 Mar 2029 04:01:39 GMT(絕對(duì)時(shí)間)
15.1.2 協(xié)商緩存
問一下服務(wù)器,這個(gè)文件有沒有過期,然后再使用這個(gè)文件
Response Headers
last-modified: Tue, 12 Mar 2019 06:22:34 GMT(絕對(duì)時(shí)間)
etag: "52-583dfb6f4de80"
向服務(wù)器請(qǐng)求資源的時(shí)候,帶上if-Modified-Since或者if-None-Match這個(gè)請(qǐng)求頭,去詢問服務(wù)器:
Request Headers
if-Modified-Since: Tue, 12 Mar 2019 06:22:34 GMT
if-None-Match: "52-583dfb6f4de80"
16. 錯(cuò)誤監(jiān)控/如何保證前端產(chǎn)品的上線質(zhì)量?
16.1 前端錯(cuò)誤的分類?
即時(shí)運(yùn)行錯(cuò)誤:代碼錯(cuò)誤
資源加載錯(cuò)誤:圖片/css/js文件加載失敗
16.2 錯(cuò)誤的捕獲方式?
16.2.1 即時(shí)運(yùn)行錯(cuò)誤的捕獲方式
// 方法一:使用try catch捕獲
try {
// ...
} catch (e) {
// error
} finally {
// handle error
}
// 方法二:使用window.onerror 捕獲錯(cuò)誤
// 無法捕獲到資源加載錯(cuò)誤
window.onerror = function(msg, url, line, col, error){
// ...
}
window.addEventListener('error', function(msg, url, line, col, error){
// ...
})
16.2.2 資源加載錯(cuò)誤(不會(huì)向上冒泡)
// 方法一: 直接在script, img這些DOM標(biāo)簽上面直接加上onerror事件
Object.onerror = function(e){
// ...
}
// 方法二:window.performace.getEntries(間接獲取資源加載錯(cuò)誤的數(shù)量)
var loadedResources = window.performance.getEntries(); // 1. 獲取瀏覽器中已經(jīng)加載的所有資源(包括各個(gè)階段的詳細(xì)加載時(shí)間)
var loaderImgs = loadedResources.filter(item => {
return /\.jpg|png|gif|svg/.test(item.name)
});
var imgs = document.getElementsByTagName('img'); // 2. 獲取頁面中所有的img集合
var len = imgs.length - loaderImgs.length; // 3. 加載失敗的圖片數(shù)量
console.log('圖片加載失敗數(shù)量:', len, '條');
// 方法三:使用事件捕獲的方式來實(shí)現(xiàn)Error事件捕獲
// 使用事件捕獲的方式來實(shí)現(xiàn)資源加載錯(cuò)誤的事件的捕獲:window ---> document --> html --- > body ---> div ---...
window.addEventListener('error', function (msg) {
console.log(msg);
}, true);
16.2.3 補(bǔ)充的方法
// 使用事件捕獲的方式來實(shí)現(xiàn)
window.addEventListener('error', function (msg) {
console.log('資源加載異常成功捕獲:', msg);
}, true);
// 使用事件冒泡的方式是只能捕獲到運(yùn)行的時(shí)候的一些異常
window.addEventListener('error', function (e) {
console.log('運(yùn)行異常成功捕獲1:', e.message, e.filename, e.lineno, e.colno, e.error);
}, false);
// 這種方式是可以按照參數(shù)的方式來接受相關(guān)的參數(shù)信息
window.onerror = function (msg, url, line, col, error) {
console.log('運(yùn)行異常成功捕獲2:', msg, url, line, col, error);
}
16.2.4 問題的延伸:跨域的js運(yùn)行錯(cuò)誤可以捕獲嗎,錯(cuò)誤提示是什么?應(yīng)該怎么處理呢?
16.2.4.1 錯(cuò)誤信息

errorinfo :
Script0 error
0 row
0 col
16.2.4.2 處理方法
第一步:在script標(biāo)簽上增加crossorigin屬性
<script crossorigin src="http://www.lmj.com/demo/crossoriginAttribute/error.js">script>
第二步:設(shè)置js資源響應(yīng)頭'Access-Control-Allow-Origin: * ',服務(wù)器端需要開啟
// 服務(wù)器可以直接設(shè)置一個(gè)響應(yīng)頭信息
res.setResponseHeader('Access-Control-Allow-Origin', 'www.lmj.com');
16.3 上報(bào)錯(cuò)誤的基本原理?
采用Ajax通信的方式來上報(bào)
利用Image對(duì)象進(jìn)行上報(bào)(cnzz)[重點(diǎn)理解掌握]
// 下面的兩種方式都是可以實(shí)現(xiàn)錯(cuò)誤信息的上報(bào)功能的
(new Image).src = 'http://www.baidu.com?name=zhangsna&age=18&sex=male'
(new Image()).src = 'https://www.baidu.com?name=zhangsan'
17. 如何使用JS獲取客戶端的硬件信息呢?
// IE 瀏覽器提供的獲取電腦硬件的API
var locator = new ActiveXObject ("WbemScripting.SWbemLocator");
var service = locator.ConnectServer(".");
var properties = service.ExecQuery("SELECT * FROM Win32_Processor");
18. 使用window.performace 來實(shí)現(xiàn)用戶體驗(yàn)的數(shù)據(jù)記錄呢?
[!NOTE]
可以參考性能優(yōu)化章節(jié)-performance性能監(jiān)控一文內(nèi)容。
三四面(業(yè)務(wù)項(xiàng)目面)
[!NOTE]
知識(shí)面要廣
理解要深刻
內(nèi)心要誠實(shí):沒了解過,問面試官有哪些資料可以學(xué)習(xí)
態(tài)度要謙虛
回答要靈活:把握一個(gè)度,不要和面試官爭(zhēng)執(zhí)對(duì)錯(cuò)
要學(xué)會(huì)贊美:被問住了可以回答,適當(dāng)贊美(沒面試官理解的那么深,虛心請(qǐng)教)
19.介紹一下你做過的項(xiàng)目?

19.1 項(xiàng)目介紹模板(業(yè)務(wù)能力體現(xiàn))
我做過什么業(yè)務(wù)?
負(fù)責(zé)的業(yè)務(wù)有什么業(yè)績(jī)?
使用了什么技術(shù)方案?
突破了什么技術(shù)難點(diǎn)?
遇到了什么問題?
最大的收獲是什么?
19.2 團(tuán)隊(duì)協(xié)作能力

19.3 事務(wù)推動(dòng)能力

19.4 帶人能力

終面(HR面)
20. 技術(shù)終面或HR面試要點(diǎn)
[!NOTE]
主要考察點(diǎn):樂觀積極、主動(dòng)溝通、邏輯順暢、上進(jìn)有責(zé)任心、有主張,做事果斷、職業(yè)競(jìng)爭(zhēng)力、職業(yè)規(guī)劃
20.1 職業(yè)競(jìng)爭(zhēng)力
業(yè)務(wù)能力:可以做到行業(yè)第一
思考能力:對(duì)同一件事可以從不同角度去思考,找到最優(yōu)解
學(xué)習(xí)能力:不斷學(xué)習(xí)新的業(yè)務(wù),沉淀、總結(jié)
無上限的付出:對(duì)于無法解決的問題可以熬夜、加班
20.2 職業(yè)規(guī)劃
目標(biāo)是什么:在業(yè)務(wù)上成為專家,在技術(shù)上成為行業(yè)大牛
近階段的目標(biāo):不斷的學(xué)習(xí)積累各方面地經(jīng)驗(yàn),以學(xué)習(xí)為主
長(zhǎng)期目標(biāo):做幾件有價(jià)值的事情,如開源作品、技術(shù)框架等
方式方法:先完成業(yè)務(wù)上的主要問題,做到極致,然后逐步向目標(biāo)靠攏
源自:https://segmentfault.com/a/1190000015288700
聲明:文章著作權(quán)歸作者所有,如有侵權(quán),請(qǐng)聯(lián)系小編刪除。
掃碼關(guān)注公眾號(hào),訂閱更多精彩內(nèi)容。

