一二面(基礎面)
1. 一面基礎面
1.1 面試準備
1.1.1 個人簡歷
- 基本資訊:姓名-年齡-手機-郵箱-籍貫
- 作業經歷:時間-公司-崗位-職責-技術堆疊-業績(哪些成就)
- 學歷: 博士 > 碩士 > 本科 > 大專
- 作業經歷:時間-公司-崗位-職責-技術堆疊-業績
- 開源專案:GitHub和說明
1.2.2 自我陳述
1.2.2.1 把我面試的溝通方向(別把自己帶到坑里面)
答:我平時喜歡研究一些網站,并對一些技術的原理和好玩的點感興趣,我自己也喜歡思考,也喜歡嘗試探索有沒有更好的方式和實作,(有所收留,不要全部說出來,稍微留一點懸念留作面試官來提問)
1.2.2.2 豁達、自信的適度發揮
答:適當自信,向自己擅長的方向上面來引路;要讓面試官來欣賞我,而不是來鄙視他,
1.2.2.3 自如談興趣
(豁達自信,適當收住),巧妙演示實體,適時討論疑問(不知道的問題請求指導一下,如何去解決,不要說不知道,或者不了解)
1.2.2.4 節奏要適宜
切忌小聰明(盡量把問題的所有實作方法都寫出來,表現出來的是熟練)
1.2 面試實戰
[!NOTE]
- 方向要對,程序要細(性能優化,程序詳細)
- 膽子要大、心態要和(演算法題認真思考,認真使勁想;敢于承擔責任,不要輕易放棄)
2. CSS相關
2.1 頁面布局
2.1.1 如何實作垂直居中布局呢?
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;
/* 盒子橫軸的對齊方式 */
justify-content: center;
/* 盒子縱軸的對齊方式 */
align-items: center;
}
/*v4.body內部居中*/
.content {
/* 1vh = 1% * 視口高度 */
margin: 50vh auto;
transform: translateY(-50%);
}
2.1.2 如何實作水平居中布局呢?
- 如果需要居中的元素為常規流中 inline / inline-block 元素,為父元素設定 text-align: center;
- 父元素上設定 text-align: center; 居中元素上margin 為 auto,
- 如果元素positon: absolute; 那么
- 0)設定父元素postion: relative
- 1)為元素設定寬度,
- 2)偏移量設定為 50%,
- 3)偏移方向外邊距設定為元素寬度一半乘以-1
2.1.3 如何實作三欄布局呢?
- left和right寫在center前面,并且分別左右浮動;
- 左右區域分別postion:absolute,固定到左右兩邊;中間的這個div因為是塊級元素,所以在水平方向上按照他的包容塊自動撐開,
- 父元素display: table;并且寬度為100%; 每一個子元素display: table-cell; 左右兩側添加寬度,中間不加寬度
- 包裹這個3個塊的父元素display: flex; 中間的元素flex: 1;
- 網格布局
/* 網格布局 */
.wrapper {
display: grid;
width: 100%;
grid-template-columns: 300px 1fr 300px;
}
2.2 知道CSS影片的實作嗎?
[!NOTE]
知道transition 過渡影片和animation 關鍵幀影片區別和具體實作,
- 1.CSS影片實作輪播圖
- 2.CSS影片實作旋轉的硬幣
- 3.CSS影片實作鐘擺效果
2.3 CSS盒子模型
2.3.1 說一下CSS的盒子模型?標準模型和IE模型的區別?CSS如何設定這兩種模型?
-
標準盒子模型:width = content
-
IE盒子模型:width = content + pading + border
-
box-sizing : content-box
-
box-sizing : border-box
2.4 CSS樣式獲取
2.4.1 JS如何設定獲取盒子模型對應的寬度和高度?(面試重點)
- dom.style.width/height : 只能取到行內樣式的的屬性資訊(拿不到外部引入的CSS樣式資訊的)
- dom.currentStyle.width/height : 會拿到瀏覽器渲染之后的屬性資訊(IE瀏覽器)
- window.getComputedStyle(dom).width/height : Chrome/Firefox 兼容, Firefox可以通過document.defaultView.getComputedStyle(dom)的方式來獲取
- dom.getBoundingClientRect().width/height : 可以獲取距離viewport位置的寬度和高度
2.5 BFC
2.5.1 根據盒子模型解釋邊距額重疊問題?邊距重疊問題的解決方案?

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

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

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

10.3.1 開始進行DOM決議,渲染DOM Tree

10.3.2 開始進行CSS決議,渲染CSSOM Tree

10.3.3 DOM樹和CSS樹的結合,最后會轉換為Render Tree

10.3.4 Layout的程序,計算每一個DOM元素的位置、寬度、高度等資訊,最終渲染并顯示頁面到瀏覽器

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

errorinfo :
Script0 error
0 row
0 col
16.2.4.2 處理方法
- 第一步:在script標簽上增加crossorigin屬性
<!-- script 表情添加crossorigin屬性 -->
<!-- 除了 script,所有能引入跨域資源的標簽包括 link 和 img 之類,都有一樣的屬性 -->
<script crossorigin src="http://www.lmj.com/demo/crossoriginAttribute/error.js"></script>
- 第二步:設定js資源回應頭'Access-Control-Allow-Origin: * ',服務器端需要開啟
// 服務器可以直接設定一個回應頭資訊
res.setResponseHeader('Access-Control-Allow-Origin', 'www.lmj.com');
16.3 上報錯誤的基本原理?
- 采用Ajax通信的方式來上報
- 利用Image物件進行上報(cnzz)[重點理解掌握]
// 下面的兩種方式都是可以實作錯誤資訊的上報功能的
(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 來實作用戶體驗的資料記錄呢?
[!NOTE]
可以參考性能優化章節-performance性能監控一文內容,
三四面(業務專案面)
[!NOTE]
- 知識面要廣
- 理解要深刻
- 內心要誠實:沒了解過,問面試官有哪些資料可以學習
- 態度要謙虛
- 回答要靈活:把握一個度,不要和面試官爭執對錯
-
- 要學會贊美:被問住了可以回答,適當贊美(沒面試官理解的那么深,虛心請教)
19.介紹一下你做過的專案?

19.1 專案介紹模板(業務能力體現)
- 我做過什么業務?
- 負責的業務有什么業績?
- 使用了什么技術方案?
- 突破了什么技術難點?
- 遇到了什么問題?
- 最大的識訓是什么?
19.2 團隊協作能力

19.3 事務推動能力

19.4 帶人能力

終面(HR面)
20. 技術終面或HR面試要點
[!NOTE]
主要考察點:樂觀積極、主動溝通、邏輯順暢、上進有責任心、有主張,做事果斷、職業競爭力、職業規劃
20.1 職業競爭力
-
業務能力:可以做到行業第一
-
思考能力:對同一件事可以從不同角度去思考,找到最優解
-
學習能力:不斷學習新的業務,沉淀、總結
-
無上限的付出:對于無法解決的問題可以熬夜、加班
20.2 職業規劃
-
目標是什么:在業務上成為專家,在技術上成為行業大牛
-
近階段的目標:不斷的學習積累各方面地經驗,以學習為主
-
長期目標:做幾件有價值的事情,如開源作品、技術框架等
-
方式方法:先完成業務上的主要問題,做到極致,然后逐步向目標靠攏
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/98425.html
標籤:Html/Css
上一篇:CSS3總結
