我的總結的比較全面的前端面試知識點。主要是一些我的認爲面試時容易考到以及平時須要注意的一些知識點。javascript
本人只是對這些知識進行了一個大概的總結,還有一部分技術還沒開始涉及,後期會持續添加。若是須要進行深刻了解能夠根據知識點查詢相關的技術文章。css
本文涵蓋了如下各個方面的知識:html
HTML, CSS, JS基礎知識前端
網站性能優化知識html5
前端項目自動化構建相關知識java
算法相關知識jquery
網絡與HTTP協議相關知識css3
前端的安全相關知識git
插件編寫相關知識github
JS模塊化編程相關知識
Github Repo:
https://github.com/Erichain/Front-End-Interview-Points
持續更新中。歡迎fork和star進行完善。
混雜模式
標準模式
準標準模式
去掉或者丟失樣式的時候可以讓頁面呈現出清晰的結構
有利於SEO:和搜索引擎創建良好溝通,有助於爬蟲抓取更多的有效信息:爬蟲依賴於標籤來肯定上下文和各個關鍵字的權重
方便其餘設備解析(如屏幕閱讀器、盲人閱讀器、移動設備)以意義的方式來渲染網頁
便於團隊開發和維護,語義化更具可讀性,是下一步網頁的重要動向,遵循W3C標準的團隊都遵循這個標準,能夠減小差別化
塊級:div, ul, li, ol, table, th, tbody, tfoot, tr, pre, fieldset, form, h1-6, p等
a, abbr, b, br, code, em, img, input, label, select, textarea, strong等
如何在不使用JS的狀況下刷新頁面(http-equiv="refresh", content="time")
設置頁面緩存
移動端設置
etc.
標籤嵌套層級不要太深,標籤儘可能簡潔化.如懶加載後將data屬性去除
大量圖片的懶加載策略,以及一些元素利用ajax在onload後實行延遲加載
對一些js的異步加載
使用空標籤設置clear: both;
爲父級元素設置overflow: hidden;
(利用BFC的原理)
使用僞元素,爲要清除浮動的元素添加.clearfix
類(推薦)
使用min-height: contain-floats;
(不推薦,兼容性很差)
觸發條件
position
屬性不爲static
或者relative
float
屬性不爲none
非塊級的塊級元素(inline-block, table-cell)
overflow
不爲visible
特性
內部的Box會在垂直方向,從頂部開始一個接一個地放置
Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生疊加
BFC的區域不會與float box疊加
BFC就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面的元素,反之亦然
計算BFC的高度時,浮動元素也參與計算
用處
解決margin邊距疊加問題。爲元素單首創建一個BFC來防止外邊距的摺疊
佈局
清除浮動。爲包含浮動元素的container建立BFC來清除浮動
總寬度 = margin+padding+border+content,IE的盒子模型的寬度不計padding和border
css3的box-sizing
屬性,詳見https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing
content-box,border和padding不計算入width以內
border-box,border和padding計算入width以內
定位和浮動的區別
何時使用定位,何時使用浮動
可繼承的樣式
font-size
font-family
color
text-indent
條件hack
<!--[if IE]><![endif]-->
屬性hack
_
IE6
*+
IE7
+
IE6/7
.
IE8
選擇符hack
*
IE7
_
IE6
減小請求
雙飛翼佈局
聖盃佈局
行內樣式 > 內聯樣式 > 外部樣式,ID > Class > Element
設置了!important
的樣式優先級更高
link屬於XHTML標籤,而@import是CSS提供的
頁面被加載的時,link會同時被加載,而@import引用的CSS會等到頁面被加載完再加載
@import只在IE5以上才能識別,而link是XHTML標籤,無兼容問題
link方式的樣式的權重 高於@import的權重
設置父元素font-size
爲0,再對裏面的文字單獨設置font-size
全兼容的樣式解決方法
.finally-solve { letter-spacing: -4px; /*根據不一樣字體字號或許須要作必定的調整*/ word-spacing: -4px; font-size: 0; } .finally-solve li { font-size: 16px; letter-spacing: normal; word-spacing: normal; display:inline-block; *display: inline; zoom:1; }
嵌套層級不要太深,通常三層最多
css解析從右向左,因此最右邊的應該是相對少一點
html用了base64的img的話,並不會緩存起來,能夠將這個base64的圖片放在css文件裏,css會緩存,圖片就緩存起來了
儘可能不用後代元素選擇器,最右邊的一層不要是標籤,尤爲是像div這種很是經常使用的標籤
多使用css的繼承,而不是每一次都書寫時都所有重寫一遍。寫多個css屬性時,能連在一塊兒寫的就連在一塊兒寫
Sass
'use strict'
不能使用eval()
抑制this
的行爲
不容許讀寫eval
和arguments
的值
不容許意外建立全局變量
使用var定義的全局變量不能使用delete刪除
無var建立的全局變量可使用delete刪除
隱式類型轉換
數字與字符串相加,結果爲字符串
數字與字符串相減,結果爲數字
比較變量的是否相同時,要採用===
,==
會發生隱式類型轉換
NaN與任何變量不相等
typeof
instanceof
constructor
Object.prototype.toString.apply()
全局做用域
函數做用域
hasOwnProperty, isPrototypeOf, propertyIsEnumerable
配置屬性(configurable, enumerable, writable, value
)
特性
擴展: isExtensible
, preventExtensions
(是否能夠添加新的屬性)
密封: isSealed
, seal
(是否能夠刪除屬性,是否能夠配置屬性)
凍結: isFrozen
, freeze
(全部屬性是否可讀可寫)
定義屬性
defineProperty
, defineProperties
數組的類型檢測
數組的方法
slice()
map()
every()
some()
filter()
柯里化
概念:部分求值(Partial Evaluation),是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,而且返回接受餘下的參數並且返回結果的新函數的技術
function currying( fn ) { var args = Array.prototype.slice.call(arguments, 1); return function () { var newArgs = args.concat(Array.prototype.slice.call(arguments)); return fn.apply(null, newArgs); } }
arguments對象
JS函數不存在重載,後定義的函數會覆蓋先定義的函數
函數調用模式
方法調用
函數調用
構造器調用
apply調用
new
操做符的原理使用new
關鍵字來建立實例的時候,原理以下:
首先,在構造函數內部使用Object.create(constructor.prototype)
建立一個對象繼承自構造函數
而後,將這個對象引用到this
上
最後,返回this
概念
做用
建立匿名執行函數
緩存變量,防止被垃圾回收
實現函數的封裝
應用場景
內部函數訪問外部函數的變量
使用閉包代替全局變量
封裝相關功能
回調函數
建立私有變量和公有變量
特性
經典例子:列表點擊,彈出每個的index
/* 錯誤作法 */ var elems = document.getElementById('links').getElementsByTagName('li'); for ( var i = 0; i < elems.length; i++ ) { elems[i].addEventListener('click', function ( event ) { event.preventDefault(); alert(i); }, false); }
/* 正確的作法,使用閉包 */ var elems = document.getElementById('links').getElementsByTagName('li'); for ( var i = 0; i < elems.length; i++ ) { (function ( index ) { elems[i].addEventListener('click', function ( event ) { event.preventDefault(); alert(index); }, false); })( i ); }
函數的this
的值永遠綁定在調用此函數的對象上
可使用apply
,call
或者bind
改變this
值的指向
工廠模式
/* 缺點:沒法檢測對象的類型 */ var createPerson = function ( name, age, job ) { var o = new Object(); o.name = name; o.age = age; o.job = job; return o; }; var person1 = createPerson('Erichain', 21, 'Web');
構造函數模式
/* 缺點:每一個方法要在每一個實例上從新建立一遍 */ var Person = function ( name, age, job ) { this.name = name; this.age = age; this.job = job; } var person1 = new Person('Erichain', 21, 'Web');
原型模式
var Person = function () {}; Person.prototype = { constructor: Person, // 若是這個屬性十分重要的話 name: 'Erichain', age: 21, job: 'web' }; var person1 = new Person();
組合構造函數原型模式
動態原型模式
var Person = function ( name, age, job ) { this.name = name; this.age = age; this.job = job; if ( typeof this.sayName !== 'function' ) { Person.prototype.sayName = function () { alert( this.name ); } } };
寄生構造函數模式
除了使用new
來實例化外,與工廠模式沒區別
不能依賴instanceof
來肯定對象類型,通常不建議使用
穩妥構造函數模式
原型鏈
借用構造函數
function Person( name ) { this.name = name; } function man() { // 繼承自Person,能夠選擇是否傳入參數 Person.call(this, 'Erichain'); }
組合繼承
原型式繼承
寄生式繼承
寄生組合式繼承
new Object()
和Object.create()
的區別
Object.create
建立的對象直接從他的第一個參數繼承,而new Object
所建立的對象是從對象的原型上繼承
使用Object.create
,能夠建立一個不繼承於任何東西的對象,可是,若是設置someConstructor.prototype = null
,那麼,這個新建立的對象會繼承自Object.prototype
函數聲明優於變量聲明
函數聲明會覆蓋變量聲明,可是不會覆蓋變量賦值
在閉包中保存變量狀態
模塊化
IIFE和自執行函數的區別
IIFE的幾種表示方法
(function () {})(); (function () {}()); !function () { /* code */ } (); ~function () { /* code */ } (); -function () { /* code */ } (); +function () { /* code */ } ();
事件流
事件捕獲
處於目標
事件冒泡
事件對象(IE的區別)
跨瀏覽器事件處理函數
var EventUtil = { getEvent: function ( event ) { return event ? event : window.event; }, getTarget: function ( event ) { return event.target || event.srcElement; }, addHandler: function ( elem, type, handler ) { if ( elem.addEventListener ) { elem.addEventListener(type, handler, false); } else if ( elem.attachEvent ) { elem.attachEvent('on' + type, handler); } else { elem['on' + type] = handler; } }, preventDefault: function ( event ) { if ( event.preventDefault ) { event.preventDefault(); } else { event.returnValue = false; } }, stopPropagation: function ( event ) { if ( event.stopPropagation ) { event.stopPropagation(); } else { event.cancelable = true; } } };
事件廣播
事件委託
<ul id="links"> <li id="link1">Link1</li> <li id="link2">Link2</li> <li id="link3">Link3</li> </ul>
var links = document.getElementById('links'); // 使用以前定義的跨瀏覽器事件處理程序 EventUtil.addHandler(links, 'click', function ( event ) { var target = EventUtil.getTarget(event); event = EventUtil.getEvent(event); switch ( target.id ) { case 'link1': // do something break; case 'link2': // do something break; case 'link3': // do something break; } });
事件函數的參數(注意addEventListener()
的最後一個參數,若是爲false表示在冒泡階段獲取事件,若是爲true,表示在事件捕獲階段獲取事件)
call(obj, args)
, apply(obj, array)
call
與apply
支持低版本瀏覽器,bind
只支持高版本瀏覽器
bind
原生代碼實現
if ( !Function.prototype.bind ) { Function.prototype.bind = function ( oThis ) { if ( typeof this !== 'function') { throw new Error('What is trying to be bound is not callable'); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBound = this, fNOP = function () {}, fBound = function () { return fToBound.apply( this instanceof fNOP ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)) ) }; if ( this.prototype ) { fNOP.prototype = this.prototype; } fBound.prototype = new fNOP(); return fBound; }; }
window
對象
location
對象
screen
對象
navigator
對象
檢測插件navigator.plugins
檢測用戶代理navigator.userAgent
history
對象
查找
document.getElementById
document.getElementsByTagName
document.getElementsByName
document.getElementsByClassName
document.querySelector
document.querySelectAll
節點關係
element.childNodes
element.firstChild
element.lastChild
element.previousSibling
element.nextSibling
element.parentNode
element.appendChild()
element.insertBefore()
element.removeChild()
element.replaceChild()
屬性操做
element.getAttribute()
element.setAttribute()
樣式操做
element.style[PROPERTY_NAME]
element.classList
element.classList.add
element.classList.remove
element.classList.contains
element.classList.toggle
元素遍歷
childElementCount
子元素數量
firstElementChild
第一個子元素: firstChild
的元素版
lastElementChild
最後一個子元素: lastChild
的元素版
previousElementSibling
->previousSibling
的元素版
nextElementSibling
->nextSibling
的元素版
遍歷方法
document.createNodeIterator(root, whatToShow, filter)
參見https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator
document.createTreeWalker(root, whatToShow, filter, expandEntityReferences, currentNode)
參見https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker
操做DOM的時候必定要緩存變量,避免發生大量的重排重繪
異步加載Javascript文件
使用document.write()
動態改變已有script標籤的src
屬性
使用DOM方法動態建立script元素
使用Ajax獲取腳本內容再加載
在script標籤中使用defer
以及async
屬性
按需加載
合併文件
合理使用二進制
CDN加速,原理
圖片懶加載
預加載
prefetch
函數節流
引用計數
/* 出現循環引用的例子 */ function () { var objectA = {}, objectB = {}; objectA.someOtherObject = objectB; objectB.anotherObject = objectA; }
標記清除
setTimeout 的第一個參數使用字符串而非函數的話,會引起內存泄漏
循環引用
優雅降級:Web站點在全部新式瀏覽器中都能正常工做,若是用戶使用的是老式瀏覽器,則代碼會檢查以確認它們是否能正常工做。因爲IE獨特的盒模型佈局問題,針對不一樣版本的IE的hack實踐過優雅降級了,爲那些沒法支持功能的瀏覽器增長候選方案,使之在舊式瀏覽器上以某種形式降級體驗卻不至於徹底失效
漸進加強:從被全部瀏覽器支持的基本功能開始,逐步地添加那些只有新式瀏覽器才支持的功能,向頁面增長無害於基礎瀏覽器的額外樣式和功能的。當瀏覽器支持時,它們會自動地呈現出來併發揮做用
JSON.stringify()
json序列化爲字符串
JSON.parse()
將類JSON的字符串轉化爲JSON對象
一段比較完整的使用原生Javascript實現ajax請求方法
function createRequestObject() { if ( window.XMLHttpRequest ) { return new XMLHttpRequest(); } // 針對IE else if ( window.ActiveXObject ) { return new ActiveXObject('Microsoft.XMLHTTP'); } } // 請求的回調函數 function requestCallBack() { if ( request.readyState === 4 && request.status === 200 ) { console.log(request.responseText); } } var request = createRequestObject(); request.onreadystatechange = requestCallBack; // open函數的三個參數分別是請求的方法, 請求的地址, 是否異步(true表示異步) request.open('POST', url, true); request.send(null);
JSHint
JSLint
ESLint(針對ECMAScript 2015)
JSMin
YUI Compressor
Gzip
Array.prototype.slice.call()
原理IE: Trident
Chrome: Webkit, Blink(now)
Firefox: Gecko
Opera: Presto
cookie 由服務器生成,可設置失效時間。若是是瀏覽器端生成的cookie,則在瀏覽器關閉以後失效;而localStorage除非被清除,不然永久保存,sessionStorage則在關閉瀏覽器或者頁面以後清除
cookie的大小爲4k左右,localStorage和sessionStorage的大小通常爲5MB
與服務器痛心的時候,cookie每次都會攜帶在http頭中,可是其餘兩個不參與服務器通訊
cookie中最好不要放置任何的明文的東西,其餘兩個的數據若是提交到服務器必定要校驗
防止XSS(跨站點腳本)攻擊
防止CSRF(跨站點僞造請求攻擊)
防止跨iframe攻擊
Unix流
管道
管道是一個固定大小的緩衝區
從管道讀數據是一次性操做,數據一旦被讀,它就從管道中被拋棄,釋放空間以便寫更多的數據
能夠把一個進程的標準輸出流與另外一個進程的標準輸入流鏈接起來
Mocha
Karma
Jasmine
同源策略指的是:協議,域名,端口相同,同源策略是一種安全協議。 指一段腳本只能讀取來自同一來源的窗口和文檔的屬性
JSONP
document.domain
window.name
HTML5的window.postMessage
和window.onmessage
三次握手
客戶端發起鏈接試探
服務端接收到試探請求,向客戶端發送確認消息
客戶端獲得服務端的確認消息以後,再次向服務端發送確認消息
一次完整的http請求是怎麼樣的
域名解析
TCP三次握手
發起http請求
服務器端響應http請求,客戶端獲得html代碼
瀏覽器解析html代碼,並請求html代碼中的資源
瀏覽器對頁面進行渲染呈現給用戶
如何組織jQuery項目的代碼結構
柵格佈局實現原理
.img-responsive
實現原理
內聯表單實現原理
Bootstrap組件實現原理
雙向綁定
$digest
循環
dirty checking
$watch
MVC
獨立做用域
依賴注入
循環監聽
ng-if
與ng-hide/show
的區別
ng-if
爲true
的時候節點纔會存在於DOM中
ng-show/hide
只是控制節點的顯示和隱藏
factory
,service
與provider
的區別和關係
使用factory
建立的服務,是一個對象,而後,將方法和屬性定義在這個對象上,在返回這個對象,就能夠供外部controller調用了
使用service
建立的服務,是使用new
進行實例化的,因此,方法和屬性要定義在this
上,而且這個服務會自動返回this
使用provider
建立的服務,是惟一能夠注入到config()
函數的服務,能夠用來提供模塊化的配置。而且,定義在this
上的屬性和方法,在config
函數裏才能夠訪問,從this.$get()
函數裏返回的屬性和方法,才能被控制器所訪問
ng-click
是否可使用原生函數
不能夠,由於對應的方法不存在於其控制器中,除非在控制器中聲明
ng-repeat
數組中有相同元素的解決辦法
能夠添加track by $index
$emit
,$broadcast
和$on
$emit
由子級向父級廣播,$broadcast
由父級向子級廣播
controllerAs
與$scope
的區別
AngularJS的缺點
強約束,學習成本高
不利於SEO
性能問題
減小監控項
主動設置索引
下降渲染的數據數量
數據扁平化
最簡單的方法
function removeDuplicate( arr ) { var len = arr.length, temp = []; for ( var i = 0; i < len; i+=1 ) { if ( temp.indexOf(arr[i]) === -1 ) { temp.push(arr[i]); } } return temp; }
function clone( Obj ) { var buf; if ( Obj instanceof Array ) { buf = []; //建立一個空的數組 var i = Obj.length; while ( i-- ) { buf[i] = clone(Obj[i]); } return buf; } else if ( Obj instanceof Object ) { buf = {}; //建立一個空對象 for ( var k in Obj ) { //爲這個對象添加新的屬性 buf[k] = clone(Obj[k]); } return buf; } else { return Obj; } }
function clone( obj ) { var dest; switch( typeof obj ) { case 'undefined': break; case 'number': dest = +obj; break; case 'string': dest = obj + ''; break; case 'boolean': dest = obj; break; case 'object': if ( obj instanceof Array ) { dest = []; for ( var i = 0; i < obj.length; i++ ) { dest[i] = obj[i]; } } else { dest = {}; for ( var i in obj ) { dest[i] = obj[i]; } } default: break; } return dest; }
快速排序
function quickSort( arr ) { var left = [], right = [], len = arr.length, breakPoint = arr[0]; if ( len === 1 || len === 0 ) { return arr; } for ( var i = 1; i < len; i++ ) { if ( arr[i] < breakPoint ) { left.push(arr[i]); } else { right.push(arr[i]); } } return quickSort(left).concat(breakPoint, quickSort(right)); }
冒泡排序
function bubbleSort( arr ) { var len = arr.length, temp; for ( var i = 0; i < len - 1; i ++ ) { for ( var j = 0; j < len - 1 - i; j++ ) { if ( arr[j] > arr[j+1] ) { temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } return arr; }
插入排序
function insertSort( arr ) { var len = arr.length, temp; for ( var i = 1; i < len; i++ ) { var j; temp = arr[i]; j = i; while ( j > 0 && arr[j-1] > temp ) { arr[j] = arr[j-1]; j--; } arr[j] = temp; } return arr; }
function removePlace( str ) { var reg = /(^s*)|(s*)$/; if ( str && typeof str === 'string' ) { return str.replace(reg, ''); } }
function charCount( str ) { var obj = {}, len = str.length, i = 0; for ( ; i < len; i++ ) { var val = str.charAt(i); if ( obj[val] && obj[val].value === val ) { obj[val].count++; } else { obj[val] = {}; obj[val].count = 1; obj[val].value = val; } } for ( var key in obj ) { console.log( key + ' is ' + obj[key].count ); } return obj; }
關於插件編寫,可參考:jQuery插件庫
同步的方式加載模塊,服務器優先
使用require
加載模塊,使用module.exports
定義模塊
瀏覽器優先的方式,經過異步加載的方式完成任務
使用define(['module'], function ( module ) {})
加載模塊
不兼容 io、文件系統(filesystem)和其它經過 CommonJS 實現的面向服務器的功能
推崇依賴前置
對於依賴的模塊提早執行
推崇依賴就近
對於依賴的模塊延遲執行
使用define(function ( require, exports, module ) {})
加載模塊
同時支持 AMD 和 CommonJS 特性