前端面試題總結
基本信息
- 為何選擇前端這個方向?
- 第一的話對互聯網開發方面的東西很感興趣,之前也接觸過其他語言,但是直到接觸到前端才發現很有興趣做下去,興趣是一個人最好的老師。
- 第二的話前端的發展前景也很廣闊,像現在的nodejs,微信小程序這類工具和框架可以讓前端進行后端和移動開發,所以我覺得從事前端工作未來也會有很好的發展。
- 對前端的理解?
- 首先前端的核心技能還是:HTML,CSS,JS。前端負責的是用戶可以看到的部分,所以也是最接近用戶的工程師。同時在產品研發流程中前端要同時與產品、設計、后端等很多人合作。
- 平時是怎么學新技術的?
- 伯樂在線、infoq、掘金、簡書、慕課網
- 對自己未來的規划是怎樣的
- 對於剛畢業的人來說,前兩年是很重要的,先打好基礎,多提升js能力。三至四年在提升JS能力的同時,開始要往多方面發展,前端工程師遠遠不僅是JS而已。制作一個性能高、交互好、視覺美的頁面,需要從前端框架選型、架構設計、構建工具,到后端通信機制、設計與交互、網絡和瀏覽器優化等各方面的知識。一專多長才是前端工程師的終極目標。
- 你覺得前端工程的價值體現在哪
- 為簡化用戶使用提供技術支持(交互部分)
- 為多個瀏覽器兼容性提供支持
- 為提高用戶瀏覽速度(瀏覽器性能)提供支持
- 為跨平台或者其他基於webkit或其他渲染引擎的應用提供支持
- 為展示數據提供支持(數據接口)
前端基本語言
HTML/HTML5
-
知道語義化嗎?說說你理解的語義化,如果是你,平時會怎么做來保證語義化?
- 像html5的新的標簽header,footer,section等就是語義化
- 一方面,語義化就是讓計算機能夠快速的讀懂內容,高效的處理信息,可以對搜索引擎更友好。
- 另一方面,便於與他人的協作,他人通過讀代碼就可以理解你網頁標簽的意義。
- 去掉或者丟失樣式的時候能夠讓頁面呈現出清晰的結構
- 有利於SEO:和搜索引擎建立良好溝通,有助於爬蟲抓取更多的有效信息:爬蟲依賴於標簽來確定上下文和各個關鍵字的權重;
- 方便其他設備解析(如屏幕閱讀器、盲人閱讀器、移動設備)以意義的方式來渲染網頁;
- 便於團隊開發和維護,語義化更具可讀性,是下一步吧網頁的重要動向,遵循W3C標准的團隊都遵循這個標准,可以減少差異化。
-
介紹一下HTML5的新特性
- 新的DOCTYPE聲明
- 完全支持css3
- video和audio
- 本地存儲
- 語義化標簽
- canvas
- 新事件 如ondrag onresize
-
如何解決ajax無法后退的問題?
- HTML5里引入了新的API,即:history.pushState, history.replaceState
- 可以通過pushState和replaceState接口操作瀏覽器歷史,並且改變當前頁面的URL。
- onpopstate監聽后退
-
websocket和ajax輪詢
- Websocket是HTML5中提出的新的協議,注意,這里是協議,可以實現客戶端與服務器端的通信,實現服務器的推送功能。
- 其優點就是,只要建立一次連接,就可以連續不斷的得到服務器推送的消息,節省帶寬和服務器端的壓力。
- ajax輪詢模擬長連接就是每個一段時間(0.5s)就向服務器發起ajax請求,查詢服務器端是否有數據更新
- 其缺點顯而易見,每次都要建立HTTP連接,即使需要傳輸的數據非常少,所以這樣很浪費帶寬
-
Web Worker 和webSocket
worker主線程:
1.通過 worker = new Worker( url ) 加載一個JS文件來創建一個worker,同時返回一個worker實例。
2.通過worker.postMessage( data ) 方法來向worker發送數據。
3.綁定worker.onmessage方法來接收worker發送過來的數據。
4.可以使用 worker.terminate() 來終止一個worker的執行。
WebSocket
- 是Web應用程序的傳輸協議,它提供了雙向的,按序到達的數據流。他是一個Html5協議,WebSocket的連接是持久的,他通過在客戶端和服務器之間保持雙工連接,服務器的更新可以被及時推送給客戶端,而不需要客戶端以一定時間間隔去輪詢。
-
Doctype作用? 嚴格模式與混雜模式如何區分?它們有何意義?
- 聲明位於文檔中的最前面,處於 標簽之前。告知瀏覽器以何種模式來渲染文檔。
- 嚴格模式的排版和 JS 運作模式是 以該瀏覽器支持的最高標准運行。
- 在混雜模式中,頁面以寬松的向后兼容的方式顯示。模擬老式瀏覽器的行為以防止站點無法工作。
- DOCTYPE不存在或格式不正確會導致文檔以混雜模式呈現。
-
你知道多少種Doctype文檔類型?
- 該標簽可聲明三種 DTD 類型,分別表示嚴格版本、過渡版本以及基於框架的 HTML 文檔。
- HTML 4.01 規定了三種文檔類型:Strict、Transitional 以及 Frameset。
- XHTML 1.0 規定了三種 XML 文檔類型:Strict、Transitional 以及 Frameset。
- Standards (標准)模式(也就是嚴格呈現模式)用於呈現遵循最新標准的網頁,而 Quirks
- (包容)模式(也就是松散呈現模式或者兼容模式)用於呈現為傳統瀏覽器而設計的網頁。
-
HTML與XHTML——二者有什么區別
- 所有的標記都必須要有一個相應的結束標記
- 所有標簽的元素和屬性的名字都必須使用小寫
- 所有的XML標記都必須合理嵌套
- 所有的屬性必須用引號""括起來
- 把所有<和&特殊符號用編碼表示
- 給所有屬性賦一個值
- 不要在注釋內容中使“--”
- 圖片必須有說明文字
CSS
- 說說content-box和border-box,為什么看起來content-box更合理,但是還是經常使用border-box?
- content-box 是W3C的標准盒模型 元素寬度=內容寬度+padding+border
- border-box 是ie的怪異盒模型 他的元素寬度等於內容寬度 內容寬度包含了padding和border
- 比如有時候在元素基礎上添加內距padding或border會將布局撐破 但是使用border-box就可以輕松完成
-
實現三個DIV等分排布在一行(考察border-box)
1.設置border-box width33.3%
2.flexbox flex:1 -
實現兩欄布局有哪些方法
- 方法一:
*{margin:0; padding: 0;} html,body{ height: 100%;/*高度百分百顯示*/ } #left{ width: 300px; height: 100%; background-color: #ccc; float: left; } #right{ height: 100%; margin-left: 300px; background-color: #eee; - 方法二:
*{margin:0; padding: 0;} html,body{ height: 100%;/*高度百分百顯示*/ } #left{ width: 300px; height: 100%; background-color: #ccc; float: left; } #right{ height: 100%; overflow:hidden; background-color: #eee; } - 第二種方法,我利用的是創建一個新的BFC(塊級格式化上下文)來防止文字環繞的原理來實現的。BFC就是一個相對獨立的布局環境,它內部元素的布局不受外面布局的影響。它可以通過以下任何一種方式來創建:
- float 的值不為 none
- position 的值不為 static 或者 relative
- display 的值為 table-cell , table-caption , inline-block , flex , 或者 inline-flex 中的其中一個
- overflow 的值不為 visible
- 第三種flex布局
- 設置width的flex元素,flex屬性值是多少?
- flex屬性是flex-grow, flex-shrink 和 flex-basis的簡寫
- flex-grow屬性定義項目的放大比例,默認為0
- flex-shrink屬性定義了項目的縮小比例,默認為1
- flex-basis屬性定義了項目的固定空間
- 怎么實現從一個DIV左上角到右下角的移動,有哪些方法,都怎么實現?
- 改變left值為window寬度-div寬度 top值為window高度-div高度
- jquery的animate方法
- css3的transition
- 聖杯布局和雙飛翼布局
- 【聖杯布局】
html代碼中 middle部分首先要放在container的最前部分。然后是left,right- 將三者都 float:left , 再加上一個position:relative (因為相對定位后面會用到)
- middle部分 width:100%占滿
- 此時middle占滿了,所以要把left拉到最左邊,使用margin-left:-100%
- 這時left拉回來了,但會覆蓋middle內容的左端,要把middle內容拉出來,所以在外圍container加上 padding:0 220px 0 200px
- middle內容拉回來了,但left也跟着過來了,所以要還原,就對left使用相對定位 left:-200px 同理,right也要相對定位還原 right:-220px
- 到這里大概就自適應好了。如果想container高度保持一致可以給left middle right都加上min-height:130px
- 【雙飛翼布局】
- 前幾步都一樣 后邊把外圍padding和相對定位做法換成內層margin
- 給middle增加一個內層div-middle-inner, 然后margin:0 220px 0 200px
- 47:offsetHeight, scrollHeight, clientHeight分別代表什么
- clientHeight:包括內容可見部分的高度,可見的padding;不包括border,水平方向的scrollbar,margin。
- offsetHeight:包括內容可見部分的高度,border,可見的padding,水平方向的scrollbar(如果存在);不包括margin。
- scrollHeight:包括內容的高度(可見與不可見),padding(可見與不可見);不包括border,margin。
- 垂直居中
- 單行行內元素
- 可以設置padding-top,padding-bottom
- 將height和line-height設為相等
- 多行行內元素
- 可以將元素轉為table樣式,再設置vertical-align:middle;
- 使用flex布局
- 塊級元素
- 已知高度絕對定位負邊距
- 未知高度transform: translateY(-50%);
- flex布局
display: flex; justify-content: center; align-items: center;
- rem和em的區別?
- em相對於父元素,rem相對於根元素
- 清除浮動
- 談談浮動和清除浮動:浮動的框可以向左或向右移動,直到他的外邊緣碰到包含框或另一個浮動框的邊框為止。由於浮動框不在文檔的普通流中,所以文檔的普通流的塊框表現得就像浮動框不存在一樣。浮動的塊框會漂浮在文檔普通流的塊框上。
- 兩種原理
- 利用clear屬性進行清理
- 具體的實現原理是通過引入清除區域,這個相當於加了一塊看不見的框把定義clear屬性的元素向下擠
- 父容器結尾插入空標簽
<div style="clear: both;"></div> - 利用CSS偽元素:
.clearfix:after { content: "."; height: 0; visibility: hidden; display: block; clear: both; }- 將父容器形成BFC
- BFC能清理浮動主要運用的是它的布局規則:
- 內部的Box會在垂直方向,一個接一個地放置。
- Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊
- 每個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對於從左往右的格式化,否則相反)。即使存在浮動也是如此。
- BFC的區域不會與float box重疊。
- BFC就是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素。反之也如此。
- 計算BFC的高度時,浮動元素也參與計算
- 浮動清理利用的主要是第六條規則,只要將父容器觸發為BFC,就可以實現包含的效果。那么觸發BFC有哪幾種方法?
- 根元素
- float屬性不為none
- position為absolute或fixed
- display為inline-block, table-cell, table-caption, flex, inline-flex
- overflow不為visible
-
position的值, relative和absolute分別是相對於誰進行定位的?
- relative:相對定位,相對於自己本身在正常文檔流中的位置進行定位。
- absolute:生成絕對定位,相對於最近一級定位不為static的父元素進行定位。
- fixed: (老版本IE不支持)生成絕對定位,相對於瀏覽器窗口或者frame進行定位。
- static:默認值,沒有定位,元素出現在正常的文檔流中。
- sticky:生成粘性定位的元素,容器的位置根據正常文檔流計算得出。
-
position:absolute和float屬性的異同?
- 共同點:對內聯元素設置float和absolute屬性,可以讓元素脫離文檔流,並且可以設置其寬高。
- 不同點:float仍可占據位置,不會覆蓋在另一個BFC區域上,浮動的框可以向左或向右移動,直到它的外邊緣碰到包含框或另一個浮動框的邊框為止。absolute會覆蓋文檔流中的其他元素。
-
CSS 選擇符有哪些?哪些屬性可以繼承?優先級算法如何計算? CSS3新增偽類有那些?
-
選擇符:
- id選擇器(#myId);
- 類選擇器(.myClassName);
- 標簽選擇器(div,p,h1);
- 相鄰選擇器(h1 + p);
- 子選擇器(ul > li);
- 后代選擇器(li a);
- 通配符選擇器(*);
- 屬性選擇器(button[disabled="true"]);
- 偽類選擇器(a:hover,li:nth-child);表示一種狀態
- 偽元素選擇器(li:before、:after,:first-letter,:first-line,:selecton);表示文檔某個部分的表現
-
優先級:
!important > 行內樣式(比重1000) > id(比重100) > class/屬性(比重10) > tag / 偽類(比重1); -
偽類和偽元素區別:
- 偽類:a:hover,li:nth-child;
- 偽元素:li:before、:after,:first-letter,:first-line,:selecton;
-
-
介紹sass
- &定義變量 css嵌套 允許在代碼中使用算式 支持if判斷for循環
-
tansition和margin的百分比根據什么計算?
- transition是相對於自身,margin相對於參照物
-
實現一個秒針繞一點轉動的效果
animation: move 60s infinite steps(60);
/*設置旋轉的中心點為中間底部*/
transform-origin: center bottom;
/*旋轉從0度到360度*/
@keyframes move {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
-
display:none和visibility:hidden的區別?
- display:none 隱藏對應的元素,在文檔布局中不再給它分配空間,它各邊的元素會合攏,就當他從來不存在。
- visibility:hidden 隱藏對應的元素,但是在文檔布局中仍保留原來的空間。
-
CSS中link 和@import的區別是?
- link屬於HTML標簽,而@import是CSS提供的;
- 頁面被加載的時,link會同時被加載,而@import被引用的CSS會等到引用它的CSS文件被加載完再加載;
- import只在IE5以上才能識別,而link是HTML標簽,無兼容問題;
- link方式的樣式的權重 高於@import的權重.
-
position:absolute和float屬性的異同
- 共同點:對內聯元素設置float和absolute屬性,可以讓元素脫離文檔流,並且可以設置其寬高。
- 不同點:float仍會占據位置,absolute會覆蓋文檔流中的其他元素。
-
介紹一下box-sizing屬性?
- box-sizing屬性主要用來控制元素的盒模型的解析模式。默認值是content-box。
- content-box:讓元素維持W3C的標准盒模型。元素的寬度/高度由border + padding + content的寬度/高度決定,設置width/height屬性指的是content部分的寬/高
- border-box:讓元素維持IE傳統盒模型(IE6以下版本和IE6~7的怪異模式)。設置width/height屬性指的是border + padding + content
- 標准瀏覽器下,按照W3C規范對盒模型解析,一旦修改了元素的邊框或內距,就會影響元素的盒子尺寸,就不得不重新計算元素的盒子尺寸,從而影響整個頁面的布局。
-
CSS3新增偽類舉例
- p:first-of-type 選擇屬於其父元素的首個
元素的每個
元素。
- p:last-of-type 選擇屬於其父元素的最后
元素的每個
元素。
- p:only-of-type 選擇屬於其父元素唯一的
元素的每個
元素。
- p:only-child 選擇屬於其父元素的唯一子元素的每個
元素。
- p:nth-child(2) 選擇屬於其父元素的第二個子元素的每個
元素。
- :enabled :disabled 控制表單控件的禁用狀態。
- :checked 單選框或復選框被選中。
- p:first-of-type 選擇屬於其父元素的首個
-
CSS3有哪些新特性?
- CSS3實現圓角(border-radius),陰影(box-shadow),
- 對文字加特效(text-shadow、),線性漸變(gradient),旋轉(transform)
- transform:rotate(9deg) scale(0.85,0.90) translate(0px,-30px) skew(-9deg,0deg);//旋轉,縮放,定位,傾斜
- 增加了更多的CSS選擇器 多背景 rgba
- 在CSS3中唯一引入的偽元素是::selection.
- 媒體查詢,多欄布局
- border-image
- CSS3中新增了一種盒模型計算方式:box-sizing。盒模型默認的值是content-box, 新增的值是padding-box和border-box,幾種盒模型計算元素寬高的區別如下:
- content-box(默認)
- 布局所占寬度Width:
Width = width + padding-left + padding-right + border-left + border-right - 布局所占高度Height:
Height = height + padding-top + padding-bottom + border-top + border-bottom
- 布局所占寬度Width:
- padding-box
- 布局所占寬度Width:
Width = width(包含padding-left + padding-right) + border-top + border-bottom - 布局所占高度Height:
Height = height(包含padding-top + padding-bottom) + border-top + border-bottom
- 布局所占寬度Width:
- border-box
- 布局所占寬度Width:
Width = width(包含padding-left + padding-right + border-left + border-right) - 布局所占高度Height:
Height = height(包含padding-top + padding-bottom + border-top + border-bottom)
- 布局所占寬度Width:
- content-box(默認)
-
對BFC規范的理解?
- BFC,塊級格式化上下文,一個創建了新的BFC的盒子是獨立布局的,盒子里面的子元素的樣式不會影響到外面的元素。在同一個BFC中的兩個毗鄰的塊級盒在垂直方向(和布局方向有關系)的margin會發生折疊。
- (W3C CSS 2.1 規范中的一個概念,它決定了元素如何對其內容進行布局,以及與其他元素的關系和相互作用。
JS
- 介紹一下閉包和閉包常用場景?
使用閉包主要是為了設計私有的方法和變量。閉包的優點是可以避免全局變量的污染,缺點是閉包會常駐內存,會增大內存使用量,使用不當很容易造成內存泄露。在js中,函數即閉包,只有函數才會產生作用域的概念
- 閉包有三個特性:
- 函數嵌套函數
- 函數內部可以引用外部的參數和變量
- 參數和變量不會被垃圾回收機制回收
- 閉包是指有權訪問另一個函數作用域中的變量的函數. 創建閉包常見方式,就是在一個函數內部創建另一個函數.
- 應用場景 設置私有變量和方法
- 不適合場景:返回閉包的函數是個非常大的函數
- 閉包的缺點就是常駐內存,會增大內存使用量,使用不當很容易造成內存泄露。
- 為什么會出現閉包這種東西,解決了什么問題?
- 受JavaScript鏈式作用域結構的影響,父級變量中無法訪問到子級的變量值,為了解決這個問題,才使用閉包這個概念
- 介紹一下你所了解的作用域鏈,作用域鏈的盡頭是什么,為什么?
- 每一個函數都有一個作用域,比如我們創建了一個函數,函數里面又包含了一個函數,那么現在 就有三個作用域,這樣就形成了一個作用域鏈。
- 作用域的特點就是,先在自己的變量范圍中查找,如果找不到,就會沿着作用域鏈往上找。
- 一個Ajax建立的過程是怎樣的,主要用到哪些狀態碼?
- ajax:在不切換頁面的情況下完成異步的HTTP請求
- 創建XMLHttpRequest對象,也就是創建一個異步調用對象.
- 創建一個新的HTTP請求,並指定該HTTP請求的方法、URL及驗證信息.
- 設置響應HTTP請求狀態變化的函數.
- 發送HTTP請求.
- 獲取異步調用返回的數據.
- 使用JavaScript和DOM實現局部刷新.
var xmlHttp = new XMLHttpRequest(); xmlHttp.open('GET','demo.php','true'); xmlHttp.send() xmlHttp.onreadystatechange = function(){ if(xmlHttp.readyState === 4 & xmlHttp.status === 200){ } } - ajax:在不切換頁面的情況下完成異步的HTTP請求
- 使用promise封裝
function getJSON(url) { return new Promise(function(resolve, reject) { var XHR = new XMLHttpRequest(); XHR.open('GET', url, true); XHR.send(); XHR.onreadystatechange = function() { if (XHR.readyState == 4) { if (XHR.status == 200) { try { var response = JSON.parse(XHR.responseText); resolve(response); } catch (e) { reject(e); } } else { reject(new Error(XHR.statusText)); } } } }) } getJSON(url).then(res => console.log(res));- 當前狀態readystate
- 0 代表未初始化。 還沒有調用 open 方法
- 1 代表正在加載。 open 方法已被調用,但 send 方法還沒有被調用
- 2 代表已加載完畢。send 已被調用。請求已經開始
- 3 代表交互中。服務器正在發送響應
- 4 代表完成。響應發送完畢
- 常用狀態碼status
- 404 沒找到頁面(not found)
- 403 禁止訪問(forbidden)
- 500 內部服務器出錯(internal service error)
- 200 一切正常(ok)
- 304 沒有被修改(not modified)(服務器返回304狀態,表示源文件沒有被修改)
- 當前狀態readystate
- 說說你還知道的其他狀態碼,狀態碼的存在解決了什么問題?
- 302/307 臨時重定向
- 301 永久重定向
- 借助狀態碼,用戶可以知道服務器端是正常處理了請求,還是出現了什么錯誤
- 事件委托
- 利用冒泡的原理,把事件加到父級上,觸發執行效果。
1.可以大量節省內存占用,減少事件注冊。
2.可以方便地動態添加和修改元素,不需要因為元素的改動而修改事件綁定。var ul = document.querySelector('ul'); var list = document.querySelectorAll('ul li'); ul.addEventListener('click', function(ev){ var ev = ev || window.event; var target = ev.target || ev.srcElemnt; for(var i = 0, len = list.length; i < len; i++){ if(list[i] == target){ alert(i + "----" + target.innerHTML); } } });
- 說說你知道JavaScript的內存回收機制?
- 垃圾回收器會每隔一段時間找出那些不再使用的內存,然后為其釋放內存。
- 一般使用標記清除方法 當變量進入環境標記為進入環境,離開環境標記為離開環境
- 還有引用計數方法
- 堆棧
- stack為自動分配的內存空間,它由系統自動釋放;而heap則是動態分配的內存,大小不定也不會自動釋放。
- 基本數據類型存放在棧中
- 引用類型 存放在堆內存中,首先從棧中獲得該對象的地址指針,然后再從堆內存中取得所需的數據
- 函數防抖和函數節流?
- 函數防抖是指頻繁觸發的情況下,只有足夠的空閑時間,才執行代碼一次
- 函數防抖的要點,也是需要一個setTimeout來輔助實現。延遲執行需要跑的代碼。
- 如果方法多次觸發,則把上次記錄的延遲執行代碼用clearTimeout清掉,重新開始。
- 如果計時完畢,沒有方法進來訪問觸發,則執行代碼。
//函數防抖
var timer = false
document.getElementById("debounce").onScroll = function() {
clearTimeout(timer);
timer = setTimeout(function(){
console.log('函數防抖');
}, 300);
}
- javaScript中的this是什么,有什么用,它的指向是什么?
- 全局代碼中的this 是指向全局對象
- 作為對象的方法調用時指向調用這個函數的對象。
- 作為構造函數指向新創建的對象
- 使用apply和call設置this
- 判斷數組有哪些方法?
- a instanceof Array
- a.constructor == Array
- Object.prototype.toString.call(a) == [Object Array]
-
嚴格模式的特性?
- 嚴格模式對Javascript的語法和行為,都做了一些改變。
- 全局變量必須顯式聲明。
- 對象不能有重名的屬性
- 函數必須聲明在頂層
- 消除Javascript語法的一些不合理、不嚴謹之處,減少一些怪異行為;
- 消除代碼運行的一些不安全之處,保證代碼運行的安全;
- 提高編譯器效率,增加運行速度;
- 為未來新版本的Javascript做好鋪墊。
-
js的原型鏈,如何實現繼承?
function foo(){}
foo.prototype.z = 3;
var obj = new foo();
obj.x=1;
obj.y=2;
obj.x //1
obj.y //2
obj.z //3
-
圖片懶加載:當網頁滾動的事件被觸發 -> 執行加載圖片操作 -> 判斷圖片是否在可視區域內 -> 在,則動態將data-src的值賦予該圖片。
-
事件模型和事件代理
- 事件三個階段:事件捕獲,目標,事件冒泡(低版本ie不支持捕獲階段)
- w3c綁定事件target.addEventListener(event,handler,false)
- 解綁target.removeEventListener(eventType, handler, false)
- ie綁定 target.attachEvent(on+event, handler)
- 解綁target.detachEvent("on"+eventType, handler)
- 事件代理優點:
- 可以大量節省內存占用,減少事件注冊,比如在table上代理所有td的click事件就非常棒
- 可以實現當新增子對象時無需再次對其綁定事件,對於動態內容部分尤為合適
- bind和trigger實現:
- 創建一個類或是匿名函數,在bind和trigger函數外層作用域創建一個字典對象,用於存儲注冊的事件及響應函數列表,bind時,如果字典沒有則創建一個,key是事件名稱,value是數組,里面放着當前注冊的響應函數,如果字段中有,那么就直接push到數組即可。trigger時調出來依次觸發事件響應函數即可。
function Emitter() { this._listener = [];//_listener[自定義的事件名] = [所用執行的匿名函數1, 所用執行的匿名函數2] } //注冊事件 Emitter.prototype.bind = function(eventName, callback) { var listener = this._listener[eventName] || [];//this._listener[eventName]沒有值則將listener定義為[](數組)。 listener.push(callback); this._listener[eventName] = listener; } //觸發事件 Emitter.prototype.trigger = function(eventName) { var args = Array.prototype.slice.apply(arguments).slice(1);//atgs為獲得除了eventName后面的參數(注冊事件的參數) var listener = this._listener[eventName]; if(!Array.isArray(listener)) return;//自定義事件名不存在 listener.forEach(function(callback) { try { callback.apply(this, args); }catch(e) { console.error(e); } }) } -
setTimeout,setInterval,requestAnimationFrame之間的區別
- setInterval如果函數執行的時間很長的話,第二次的函數會放到隊列中,等函數執行完再執行第二次,導致時間間隔發生錯誤。
- 而settimeout一定是在這個時間定時結束之后,它才會執行
- requestAnimationFrame是為了做動畫專用的一個方法,這種方法對於dom節點的操作會比較頻繁。
-
webpack常用到哪些功能
- 設置入口
- 設置輸出目
- 設置loader
- extract-text-webpack-plugin將css從js代碼中抽出並合並
- 處理圖片文字等功能
- 解析jsx解析bable
-
函數組合繼承
原型繼承、構造函數繼承、call aplly繼承
var Super = function(name){
this.name = name;
}
Super.prototype.func1 = function() { console.log('func1'); }
var Sub = function(name,age) {
Super.call(this, name);
this.age = age;
}
Sub.prototype = new Super();
- 事件綁定
var addEvent = function(e, type, handler, capture ) {
if (e.addEventListener) {
e.addEventListener(type, handler, capture);
} else if (e.attachEvent) {
e.attachEvent('on'+type, handler);
} else {
e['on'+type] = handler;
}
}
-
說說你對作用域鏈的理解
- 作用域鏈的作用是保證執行環境里有權訪問的變量和函數是有序的,作用域鏈的變量只能向上訪問,變量訪問到window對象即被終止,作用域鏈向下訪問變量是不被允許的。
-
Javascript垃圾回收方法
標記清除(mark and sweep)
- 這是JavaScript最常見的垃圾回收方式,當變量進入執行環境的時候,比如函數中聲明一個變量,垃圾回收器將其標記為“進入環境”,當變量離開環境的時候(函數執行結束)將其標記為“離開環境”。
- 垃圾回收器會在運行的時候給存儲在內存中的所有變量加上標記,然后去掉環境中的變量以及被環境中變量所引用的變量(閉包),在這些完成之后仍存在標記的就是要刪除的變量了
引用計數(reference counting)
- 在低版本IE中經常會出現內存泄露,很多時候就是因為其采用引用計數方式進行垃圾回收。引用計數的策略是跟蹤記錄每個值被使用的次數,當聲明了一個 變量並將一個引用類型賦值給該變量的時候這個值的引用次數就加1,如果該變量的值變成了另外一個,則這個值得引用次數減1,當這個值的引用次數變為0的時 候,說明沒有變量在使用,這個值沒法被訪問了,因此可以將其占用的空間回收,這樣垃圾回收器會在運行的時候清理掉引用次數為0的值占用的空間。
- 在IE中雖然JavaScript對象通過標記清除的方式進行垃圾回收,但BOM與DOM對象卻是通過引用計數回收垃圾的, 也就是說只要涉及BOM及DOM就會出現循環引用問題。
- js繼承方式及其優缺點
- 原型鏈繼承的缺點
- 一是字面量重寫原型會中斷關系,使用引用類型的原型,並且子類型還無法給超類型傳遞參數。
- 借用構造函數(類式繼承)
- 借用構造函數雖然解決了剛才兩種問題,但沒有原型,則復用無從談起。所以我們需要原型鏈+借用構造函數的模式,這種模式稱為組合繼承
- 組合式繼承
- 組合式繼承是比較常用的一種繼承方法,其背后的思路是 使用原型鏈實現對原型屬性和方法的繼承,而通過借用構造函數來實現對實例屬性的繼承。這樣,既通過在原型上定義方法實現了函數復用,又保證每個實例都有它自己的屬性。
ES6
- let和const的區別?
- let聲明的變量可以改變,值和類型都可以改變,沒有限制。
- const聲明的變量不得改變值
- 平時用了ES6的哪些特性,體驗如何,和ES5有什么不同?
- let、const關鍵字,箭頭函數,字符串模板,class類,模塊化,promise
- ES5 require,react.createclass
- 簡單介紹一下promise,他解決了什么問題?
- Promise,就是一個對象,用來傳遞異步操作的消息。有三種狀態:Pending(進行中)、Resolved(已完成,又稱 Fulfilled)和 Rejected(已失敗)。
- 有了 Promise 對象,就可以將異步操作以同步操作的流程表達出來,避免了層層嵌套的回調函數。
- ES6的了解
- 新增模板字符串(為JavaScript提供了簡單的字符串插值功能)、箭頭函數(操作符左邊為輸入的參數,而右邊則是進行的操作以及返回的值Inputs=>outputs。)、for-of(用來遍歷數據—例如數組中的值。)arguments對象可被不定參數和默認參數完美代替。ES6將promise對象納入規范,提供了原生的Promise對象。增加了let和const命令,用來聲明變量。增加了塊級作用域。let命令實際上就增加了塊級作用域。ES6規定,var命令和function命令聲明的全局變量,屬於全局對象的屬性;let命令、const命令、class命令聲明的全局變量,不屬於全局對象的屬性。。還有就是引入module模塊的概念
前端框架
模塊化
- 使用模塊化加載時,模塊加載的順序是怎樣的,如果不知道,根據已有的知識,你覺得順序應該是怎么樣的
- commonjs 同步 順序執行
- AMD 提前加載,不管是否調用模塊,先解析所有模塊 requirejs 速度快 有可能浪費資源
- CMD 提前加載,在真正需要使用(依賴)模塊時才解析該模塊 seajs 按需解析 性能比AMD差
- UMD規范和ES6模塊化,Commonjs的對比?
- CommonJS是一個更偏向於服務器端的規范。用於NodeJS 是同步的
- AMD是依賴前置的
- CMD推崇依賴就近,延遲執行。可以把你的依賴寫進代碼的任意一行
- AMD和CMD都是用difine和require,但是CMD標准傾向於在使用過程中提出依賴,就是不管代碼寫到哪突然發現需要依賴另一個模塊,那就在當前代碼用require引入就可以了,規范會幫你搞定預加載,你隨便寫就可以了。但是AMD標准讓你必須提前在頭部依賴參數部分寫好(沒有寫好? 倒回去寫好咯)。這就是最明顯的區別。
- UMD寫一個文件需要兼容不同的加載規范
- ES6通過import、export實現模塊的輸入輸出。其中import命令用於輸入其他模塊提供的功能,export命令用於規定模塊的對外接口。
- 對前端模塊化的認識
AMD 是 RequireJS 在推廣過程中對模塊定義的規范化產出。
CMD 是 SeaJS 在推廣過程中對模塊定義的規范化產出。
- AMD 是提前執行,CMD 是延遲執行。
- AMD推薦的風格通過返回一個對象做為模塊對象,CommonJS的風格通過對module.exports或exports的屬性賦值來達到暴露模塊對象的目的。
CMD模塊方式
define(function(require, exports, module) {
// 模塊代碼
});
框架問題
- 什么是 MVVM , 和 MVC 是什么區別, 原理是什么?
- mvc的界面和邏輯關聯緊密,數據直接從數據庫讀取,必須通過Controller來承上啟下,通信都是單向的。mvvm的View 和 ViewModel可以互相通信,界面數據從viewmodel中獲取。
- 父子組件怎么通信的?
- vue:父組件是通過props屬性給子組件通信 在子組件里面emit,在父組件監聽
- react:props傳遞 父給子傳一個回調函數 將數據傳給父親處理
-
兄弟組件怎么通信的?
- vuex 建立一個vue實例 emit觸發事件 on監聽事件
- redux 子A -> 父 -> 子B -
生命周期有哪些, 怎么用?
- beforecreated:el 和 data 並未初始化
- created:完成了 data 數據的初始化,el沒有
- beforeMount:完成了 el 和 data 初始化
- mounted :完成掛載;updated;destroyed
- react:初始化階段、運行中階段、銷毀階段
- 初始化:getDefaultProps()和getInitialState()初始化
- componentWillMount() 在組件即將被渲染到頁面
- render() 組件渲染
- componentDidMount() 組件被渲染到頁面上,
- 運行中:shouldComponentUpdate() componentWillUpdate() render() componentDidUpdate()
- 銷毀:componentWillUnmount()
- 初始化:getDefaultProps()和getInitialState()初始化
jQuery & zepto
-
zepto和jquery區別?
- zepto比jquery體積小很多,移動端的兼容性不需要要考慮很多,jquery中的很多功能都沒有。
- width()和height()不一樣 解決用.css('width')
-
css3動畫和jquery動畫的差別?
1.css3中的過渡和animation動畫都是基於css實現機制的,屬於css范疇之內,並沒有涉及到任何語言操作。效率略高與jQuery中的animate()函數,但兼容性很差。
2.jQuery中的animate()函數可以簡單的理解為css樣式的“逐幀動畫”,是css樣式不同狀態的快速切換的結果。效率略低於css3動畫執行效率,但是兼容性好。 -
你覺得jQuery或zepto源碼有哪些寫的好的地方
- jQuery源碼封裝在一個匿名函數的自執行環境中,有助於防止變量的全局污染,然后通過傳入window對象參數,可以使window對象作為局部變量使用,好處是當jquery中訪問window對象的時候,就不用將作用域鏈退回到頂層作用域了,從而可以更快的訪問window對象。同樣,傳入undefined參數,可以縮短查找undefined時的作用域鏈。
(function( window, undefined ) { //用一個函數域包起來,就是所謂的沙箱 //在這里邊var定義的變量,屬於這個函數域內的局部變量,避免污染全局 //把當前沙箱需要的外部變量通過函數參數引入進來 //只要保證參數對內提供的接口的一致性,你還可以隨意替換傳進來的這個參數 window.jQuery = window.$ = jQuery; })( window );- jquery將一些原型屬性和方法封裝在了jquery.prototype中,為了縮短名稱,又賦值給了jquery.fn,這是很形象的寫法。
- 有一些數組或對象的方法經常能使用到,jQuery將其保存為局部變量以提高訪問速度。
- jquery實現的鏈式調用可以節約代碼,所返回的都是同一個對象,可以提高代碼效率。
AngularJS
- 如何評價AngularJS和BackboneJS
- backbone具有依賴性,依賴underscore.js。Backbone + Underscore + jQuery(or Zepto) 就比一個AngularJS 多出了2 次HTTP請求.
- Backbone的Model沒有與UI視圖數據綁定,而是需要在View中自行操作DOM來更新或讀取UI數據。AngularJS與此相反,Model直接與UI視圖綁定,Model與UI視圖的關系,通過directive封裝,AngularJS內置的通用directive,就能實現大部分操作了,也就是說,基本不必關心Model與UI視圖的關系,直接操作Model就行了,UI視圖自動更新。
- AngularJS的directive,你輸入特定數據,他就能輸出相應UI視圖。是一個比較完善的前端MVW框架,包含模板,數據雙向綁定,路由,模塊化,服務,依賴注入等所有功能,模板功能強大豐富,並且是聲明式的,自帶了豐富的 Angular 指令。
React
Vue
- Vue雙向數據綁定的實現
- vue.js采用數據劫持結合發布者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個屬性的setter,getter,在數據變動時發布消息給訂閱者(文本節點則是作為訂閱者),在收到消息后執行相應的更新操作。
- compile主要做的事情是解析模板指令,將模板中的變量替換成數據,然后初始化渲染頁面並將每個指令對應的節點綁定更新函數,添加監聽數據的訂閱者,一旦數據有變動,收到通知,更新視圖。
- MVVM作為數據綁定的入口,整合Observer、Compile和Watcher三者,通過Observer來監聽自己的model數據變化,通過Compile來解析編譯模板指令,最終利用Watcher搭起Observer和Compile之間的通信橋梁,達到數據變化-->視圖更新;視圖交互變化(input)-->數據model變更的雙向數據綁定效果。
- AngularJS采用“臟值檢測”的方法,數據發生變更后,對於所有的數據和視圖的綁定關系進行一次檢測,識別是否有數據發生了改變。
bootstrap
- bootstrap的柵格系統如何實現的?
- box-sizing: border-box;
- container row column設置百分比
框架對比
- react和vue有哪些不同,說說你對這兩個框架的看法?
- 都用了virtual DOM的方式,性能都很好
- UI上都是組件化的寫法,開發效率很高
- vue是雙向數據綁定,react是單項數據綁定,當工程規模比較大時,雙向數據綁定會很難維護
- vue適合不會持續的,小型的web應用,使用vue.js能帶來短期內較高的開發效率,否則采用react。
用過哪些設計模式?
工廠模式:
》 主要好處就是可以消除對象間的耦合,通過使用工程方法而不是new關鍵字。將所有實例化的代碼集中在一個位置防止代碼重復。
- 工廠模式解決了重復實例化的問題 ,但還有一個問題,那就是識別問題,因為根本無法 搞清楚他們到底是哪個對象的實例。
function createObject(name,age,profession){//集中實例化的函數var obj = new Object();
obj.name = name;
obj.age = age;
obj.profession = profession;
obj.move = function () {
return this.name + ' at ' + this.age + ' engaged in ' + this.profession;
};
return obj;
}
var test1 = createObject('trigkit4',22,'programmer');//第一個實例var test2 = createObject('mike',25,'engineer');//第二個實例
構造函數模式
使用構造函數的方法 ,即解決了重復實例化的問題 ,又解決了對象識別的問題,該模式與工廠模式的不同之處在於:
1.構造函數方法沒有顯示的創建對象 (new Object());
2.直接將屬性和方法賦值給 this 對象;
3.沒有 renturn 語句。
瀏覽器
- 瀏覽器原生支持module嗎,如果支持,會帶來哪些便利?
- 不支持
- 瀏覽器緩存有哪些,通常緩存有哪幾種方式?
- 強緩存:強緩存如果命中,瀏覽器直接從自己的緩存中讀取資源,不會發請求到服務器。
- 協商緩存:當強緩存沒有命中的時候,瀏覽器一定會發送一個請求到服務器,通過服務器端依據資源的另外一些http header驗證這個資源是否命中協商緩存,如果協商緩存命中,服務器會將這個請求返回(304),若未命中請求,則將資源返回客戶端,並更新本地緩存數據(200)。
- HTTP頭信息控制緩存
- Expires(強緩存)+過期時間 Expires是HTTP1.0提出的一個表示資源過期時間的header,它描述的是一個絕對時間
- Cache-control(強緩存) 描述的是一個相對時間,在進行緩存命中的時候,都是利用客戶端時間進行判斷 管理更有效,安全一些 Cache-Control: max-age=3600
- Last-Modified/If-Modified-Since(協商緩存) 標示這個響應資源的最后修改時間。Last-Modified是服務器相應給客戶端的,If-Modified-Sinces是客戶端發給服務器,服務器判斷這個緩存時間是否是最新的,是的話拿緩存。
- Etag/If-None-Match(協商緩存) etag和last-modified類似,他是發送一個字符串來標識版本。
-
跨域通信有哪些方案,各有什么不同?
-
JSONP:
- 由於同源策略的限制,XmlHttpRequest只允許請求當前源(域名、協議、端口)的資源,script標簽沒有同源限制,為了實現跨域請求,可以通過script標簽實現跨域請求,然后在服務端輸出JSON數據並執行回調函數,從而解決了跨域的數據請求。
- 通過動態
<script>元素使用,使用時為src指定一個跨域url。回調函數處理JSON數據。 - 優點:兼容性好,簡單易用,支持瀏覽器與服務器雙向通信。
- 缺點:只支持GET請求。
- 簡述原理與過程:首先在客戶端注冊一個callback, 然后把callback的名字傳給服務器。此時,服務器先生成一個function , function 名字就是傳遞上來的參數。最后將 json 數據直接以入參的方式,放置到 function 中,這樣就生成了一段 js 語法的文檔,返回給客戶端。客戶端瀏覽器,解析script標簽,並執行返回的 javascript 文檔,此時數據作為參數,傳入到了客戶端預先定義好的 callback 函數里
var url = "http://localhost:8080/crcp/rcp/t99eidt/testjson.do?jsonp=callbackfunction"; var script = document.createElement('script'); script.setAttribute('src', url); //load javascript document.getElementsByTagName('head')[0].appendChild(script); //回調函數 function callbackfunction(data){ var html=JSON.stringify(data.RESULTSET); alert(html); } -
CORS:
- 服務器端對於CORS的支持,主要就是通過設置Access-Control-Allow-Origin來進行的。如果瀏覽器檢測到相應的設置,就可以允許Ajax進行跨域的訪問。
- 通過設置Access-Control-Allow-Origin來允許跨域,cors可用ajax發請求獲取數據,但是兼容性沒有jsonp好。
-
通過修改document.domain來跨子域
- 將子域和主域的document.domain設為同一個主域.前提條件:這兩個域名必須屬於同一個基礎域名!而且所用的協議,端口都要一致,否則無法利用document.domain進行跨域
- 主域相同的使用document.domain
-
使用window.name來進行跨域
- window對象有個name屬性,該屬性有個特征:即在一個窗口(window)的生命周期內,窗口載入的所有的頁面都是共享一個window.name的,每個頁面對window.name都有讀寫的權限,window.name是持久存在一個窗口載入過的所有頁面中的
-
使用HTML5中新引進的window.postMessage方法來跨域傳送數據
- 還有flash、在服務器上設置代理頁面等跨域方式。個人認為window.name的方法既不復雜,也能兼容到幾乎所有瀏覽器,這真是極好的一種跨域方法。
-
-
移動端兼容問題
- IOS移動端click事件300ms的延遲響應
- 一些情況下對非可點擊元素如(label,span)監聽click事件,ios下不會觸發,css增加cursor:pointer就搞定了
-
XML和JSON的區別?
- 數據體積方面:JSON相對於XML來講,數據的體積小,傳遞的速度更快些。
- 數據交互方面:JSON與JavaScript的交互更加方便,更容易解析處理,更好的數據交互。
- 數據描述方面:JSON對數據的描述性比XML較差。
- 傳輸速度方面:JSON的速度要遠遠快於XML。
-
漸進增強和優雅降級
- 漸進增強 :針對低版本瀏覽器進行構建頁面,保證最基本的功能,然后再針對高級瀏覽器進行效果、交互等改進和追加功能達到更好的用戶體驗。
- 優雅降級 :一開始就構建完整的功能,然后再針對低版本瀏覽器進行兼容。
構建工具
- 介紹一下你對webpack的理解,和gulp有什么不同?
- Webpack是模塊打包工具,他會分析模塊間的依賴關系,然后使用loaders處理它們,最后生成一個優化並且合並后的靜態資源。
- gulp是前端自動化工具 能夠優化前端工作流程,比如文件合並壓縮
- webpack打包速度慢,你覺得可能的原因是什么,該如何解決
- 模塊太多。
- Webpack 可以配置 externals 來將依賴的庫指向全局變量,從而不再打包這個庫
- 談談你對webpack的看法
- WebPack 是一個模塊打包工具,你可以使用WebPack管理你的模塊依賴,並編繹輸出模塊們所需的靜態文件。它能夠很好地管理、打包Web開發中所用到的HTML、JavaScript、CSS以及各種靜態文件(圖片、字體等),讓開發過程更加高效。對於不同類型的資源,webpack有對應的模塊加載器。webpack模塊打包器會分析模塊間的依賴關系,最后 生成了優化且合並后的靜態資源。
- webpack的兩大特色:
1.code splitting(可以自動完成)
2.loader 可以處理各種類型的靜態文件,並且支持串聯操作
webpack 是以commonJS的形式來書寫腳本滴,但對 AMD/CMD 的支持也很全面,方便舊項目進行代碼遷移。 - webpack具有requireJs和browserify的功能,但仍有很多自己的新特性:
- 對 CommonJS 、 AMD 、ES6的語法做了兼容
- 對js、css、圖片等資源文件都支持打包
- 串聯式模塊加載器以及插件機制,讓其具有更好的靈活性和擴展性,例如提供對CoffeeScript、ES6的支持
- 有獨立的配置文件webpack.config.js
- 可以將代碼切割成不同的chunk,實現按需加載,降低了初始化時間
- 支持 SourceUrls 和 SourceMaps,易於調試
- 具有強大的Plugin接口,大多是內部插件,使用起來比較靈活
8.webpack 使用異步 IO 並具有多級緩存。這使得 webpack 很快且在增量編譯上更加快
網絡&存儲
- http響應中content-type包含哪些內容?
- 請求中的消息主體是用何種方式編碼
- application/x-www-form-urlencoded
- 這是最常見的 POST 提交數據的方式 按照 key1=val1&key2=val2 的方式進行編碼
- application/json
- 告訴服務端消息主體是序列化后的 JSON 字符串
- get和post有什么不同?
- get是從服務器上獲取數據,post是向服務器傳送數據
- get請求可以將查詢字符串參數追加到url的末尾; post請求應該把數據作為請求的主體提交.
- get請求數據有大小限制;post沒有
- post比get安全性更高
- cookie和session有什么聯系和區別?
- cookie數據存放在客戶的瀏覽器上,session數據放在服務器上。
- session比cookie更安全
- 單個cookie保存的數據不能超過4K,很多瀏覽器都限制一個站點最多保存20個cookie。
- 一般用cookie來存儲sessionid
- 多頁面通信有哪些方案,各有什么不同?
- localstorge在一個標簽頁里被添加、修改或刪除時,都會觸發一個storage事件,通過在另一個標簽頁里監聽storage事件,即可得到localstorge存儲的值,實現不同標簽頁之間的通信。
- settimeout+cookie
-
輸入網址后到頁面展現的過程?
-
通過dns解析獲取ip
-
tcp鏈接
-
客戶端發送http請求
-
tcp傳輸報文
-
服務器處理請求返回http報文
-
客戶端解析渲染頁面 (構建DOM樹 –> 構建渲染樹 –> 布局渲染樹:計算盒模型位置和大小 –> 繪制渲染樹)
-
前端性能優化
- 【說法一】
- 減少http請求 使用sprite圖、合並js和css文件
- 使用cdn 將用戶安排在近的服務器上
- 使用緩存 緩存ajax 使用外部的css和js以便緩存 使用expire cach-control etag
- 壓縮資源 使用gzip壓縮js和css文件
- 代碼層面 避免使用樣式表達式、通配符選擇器、樣式放在頂部、腳本放在底部
- 【說法二】
- 代碼層面:避免使用css表達式,避免使用高級選擇器,通配選擇器。
- 緩存利用:緩存Ajax,使用CDN,使用外部js和css文件以便緩存,添加Expires頭,服務端配置Etag,減少DNS查找等
- 請求數量:合並樣式和腳本,使用css圖片精靈,初始首屏之外的圖片資源按需加載,靜態資源延遲加載。
- 請求帶寬:壓縮文件,開啟GZIP,
- 代碼層面的優化
- 用hash-table來優化查找
- 少用全局變量
- 用innerHTML代替DOM操作,減少DOM操作次數,優化javascript性能
- 用setTimeout來避免頁面失去響應
- 緩存DOM節點查找的結果
- 避免使用CSS Expression
- 避免全局查詢
- 避免使用with(with會創建自己的作用域,會增加作用域鏈長度)
- 多個變量聲明合並
- 避免圖片和iFrame等的空Src。空Src會重新加載當前頁面,影響速度和效率
- 盡量避免寫在HTML標簽中寫Style屬性
-
移動端性能優化
- 盡量使用css3動畫,開啟硬件加速。
- 適當使用touch事件代替click事件。
- 避免使用css3漸變陰影效果。
- 可以用transform: translateZ(0)來開啟硬件加速。
- 不濫用Float。Float在渲染時計算量比較大,盡量減少使用
- 不濫用Web字體。Web字體需要下載,解析,重繪當前頁面,盡量減少使用。
- 合理使用requestAnimationFrame動畫代替setTimeout
- CSS中的屬性(CSS3 transitions、CSS3 3D transforms、Opacity、Canvas、WebGL、Video)會觸發GPU渲染,請合理使用。過渡使用會引發手機過耗電增加
- PC端的在移動端同樣適用
-
分域名請求圖片的原因和好處?
- 瀏覽器的並發請求數目限制是針對同一域名的,超過限制數目的請求會被阻塞
- 瀏覽器並發請求有個數限制,分域名可以同時並發請求大量圖片
-
頁面的加載順序
- html順序加載,其中js會阻塞后續dom和資源的加載,css不會阻塞dom和資源的加載但是會阻塞js的加載。
- 瀏覽器會使用prefetch對引用的資源提前下載
- 沒有 defer 或 async,瀏覽器會立即加載並執行指定的腳本
- 有 async,加載和渲染后續文檔元素的過程將和 script.js 的加載與執行並行進行(下載異步,執行同步,加載完就執行)。
- 有 defer,加載后續文檔元素的過程將和 script.js 的加載並行進行(異步),但是 script.js 的執行要在所有元素解析完成之后,DOMContentLoaded 事件觸發之前完成。
-
計算機網絡的分層概述
- tcp/ip模型:從下往上分別是鏈路層,網絡層,傳輸層,應用層
- osi模型:從下往上分別是物理層,鏈路層,網絡層,傳輸層,會話層,表示層,應用層。
-
jscss緩存問題
- 瀏覽器緩存的意義在於提高了執行效率,但是也隨之而來帶來了一些問題,導致修改了js、css,客戶端不能更新
- 都加上了一個時間戳作為版本號
<script type=”text/javascript” src=”{JS文件連接地址}?version=XXXXXXXX”></script>
-
說說TCP傳輸的三次握手四次揮手策略
- 三次握手
- 為了准確無誤地把數據送達目標處,TCP協議采用了三次握手策略。用TCP協議把數據包送出去后,TCP不會對傳送 后的情況置之不理,它一定會向對方確認是否成功送達。握手過程中使用了TCP的標志:SYN和ACK。
- 發送端首先發送一個帶SYN標志的數據包給對方。接收端收到后,回傳一個帶有SYN/ACK標志的數據包以示傳達確認信息。
- 最后,發送端再回傳一個帶ACK標志的數據包,代表“握手”結束。
- 若在握手過程中某個階段莫名中斷,TCP協議會再次以相同的順序發送相同的數據包。
- 斷開一個TCP連接則需要“四次握手”:
- 第一次揮手:主動關閉方發送一個FIN,用來關閉主動方到被動關閉方的數據傳送,也就是主動關閉方告訴被動關閉方:我已經不 會再給你發數據了(當然,在fin包之前發送出去的數據,如果沒有收到對應的ack確認報文,主動關閉方依然會重發這些數據),但是,此時主動關閉方還可 以接受數據。
- 第二次揮手:被動關閉方收到FIN包后,發送一個ACK給對方,確認序號為收到序號+1(與SYN相同,一個FIN占用一個序號)。
- 第三次揮手:被動關閉方發送一個FIN,用來關閉被動關閉方到主動關閉方的數據傳送,也就是告訴主動關閉方,我的數據也發送完了,不會再給你發數據了。
- 第四次揮手:主動關閉方收到FIN后,發送一個ACK給被動關閉方,確認序號為收到序號+1,至此,完成四次揮手。
-
TCP和UDP的區別?
- TCP(Transmission Control Protocol,傳輸控制協議)是基於連接的協議,也就是說,在正式收發數據前,必須和對方建立可靠的連接。一個TCP連接必須要經過三次“對話”才能建立起來
- UDP(User Data Protocol,用戶數據報協議)是與TCP相對應的協議。它是面向非連接的協議,它不與對方建立連接,而是直接就把數據包發送過去!
- UDP適用於一次只傳送少量數據、對可靠性要求不高的應用環境。
-
HTTP和HTTPS
- HTTP協議通常承載於TCP協議之上,在HTTP和TCP之間添加一個安全協議層(SSL或TSL),這個時候,就成了我們常說的HTTPS。
- 默認HTTP的端口號為80,HTTPS的端口號為443。
-
為什么HTTPS安全
- 因為網絡請求需要中間有很多的服務器路由器的轉發。中間的節點都可能篡改信息,而如果使用HTTPS,密鑰在你和終點站才有。https之所以比http安全,是因為他利用ssl/tls協議傳輸。它包含證書,卸載,流量轉發,負載均衡,頁面適配,瀏覽器適配,refer傳遞等。保障了傳輸過程的安全性
-
關於Http 2.0 你知道多少?
- HTTP/2引入了“服務端推(server push)”的概念,它允許服務端在客戶端需要數據之前就主動地將數據發送到客戶端緩存中,從而提高性能。
- HTTP/2提供更多的加密支持
- HTTP/2使用多路技術,允許多個消息在一個連接上同時交差。
- 它增加了頭壓縮(header compression),因此即使非常小的請求,其請求和響應的header都只會占用很小比例的帶寬。
-
defer和async
- defer並行加載js文件,會按照頁面上script標簽的順序執行
- async並行加載js文件,下載完成立即執行,不會按照頁面上script標簽的順序執行
-
請你談談Cookie的弊端
cookie雖然在持久保存客戶端數據提供了方便,分擔了服務器存儲的負擔,但還是有很多局限性的。
- 第一:每個特定的域名下最多生成20個cookie
1.IE6或更低版本最多20個cookie
2.IE7和之后的版本最后可以有50個cookie。
3.Firefox最多50個cookie
4.chrome和Safari沒有做硬性限制 - 第二:IE和Opera 會清理近期最少使用的cookie,Firefox會隨機清理cookie。
- cookie的最大大約為4096字節,為了兼容性,一般不能超過4095字節。
- IE 提供了一種存儲可以持久化用戶數據,叫做userdata,從IE5.0就開始支持。每個數據最多128K,每個域名下最多1M。這個持久化數據放在緩存中,如果緩存沒有清理,那么會一直存在。
- 優點:極高的擴展性和可用性
1.通過良好的編程,控制保存在cookie中的session對象的大小。
2.通過加密和安全傳輸技術(SSL),減少cookie被破解的可能性。
3.只在cookie中存放不敏感數據,即使被盜也不會有重大損失。
4.控制cookie的生命期,使之不會永遠有效。偷盜者很可能拿到一個過期的cookie。 - 缺點:
1.Cookie數量和長度的限制。每個domain最多只能有20條cookie,每個cookie長度不能超過4KB,否則會被截掉.
2.安全性問題。如果cookie被人攔截了,那人就可以取得所有的session信息。即使加密也與事無補,因為攔截者並不需要知道cookie的意義,他只要原樣轉發cookie就可以達到目的了。
3.有些狀態不可能保存在客戶端。例如,為了防止重復提交表單,我們需要在服務器端保存一個計數器。如果我們把這個計數器保存在客戶端,那么它起不到任何作用。
-
瀏覽器本地存儲
- 在較高版本的瀏覽器中,js提供了sessionStorage和globalStorage。在HTML5中提供了localStorage來取代globalStorage。
- html5中的Web Storage包括了兩種存儲方式:sessionStorage和localStorage。
- sessionStorage用於本地存儲一個會話(session)中的數據,這些數據只有在同一個會話中的頁面才能訪問並且當會話結束后數據也隨之銷毀。因此sessionStorage不是一種持久化的本地存儲,僅僅是會話級別的存儲。
- 而localStorage用於持久化的本地存儲,除非主動刪除數據,否則數據是永遠不會過期的。
-
web storage和cookie的區別
- Web Storage的概念和cookie相似,區別是它是為了更大容量存儲設計的。Cookie的大小是受限的,並且每次你請求一個新的頁面的時候Cookie都會被發送過去,這樣無形中浪費了帶寬,另外cookie還需要指定作用域,不可以跨域調用。
- 除此之外,Web Storage擁有setItem,getItem,removeItem,clear等方法,不像cookie需要前端開發者自己封裝setCookie,getCookie。
- 但是cookie也是不可以或缺的:cookie的作用是與服務器進行交互,作為HTTP規范的一部分而存在 ,而Web Storage僅僅是為了在本地“存儲”數據而生
- 瀏覽器的支持除了IE7及以下不支持外,其他標准瀏覽器都完全支持(ie及FF需在web服務器里運行),值得一提的是IE總是辦好事,例如IE7、IE6中的userData其實就是javascript本地存儲的解決方案。通過簡單的代碼封裝可以統一到所有的瀏覽器都支持web storage。
- localStorage和sessionStorage都具有相同的操作方法,例如setItem、getItem和removeItem等
-
cookie 和session 的區別:
- cookie數據存放在客戶的瀏覽器上,session數據放在服務器上。
- cookie不是很安全,別人可以分析存放在本地的COOKIE並進行COOKIE欺騙
- 考慮到安全應當使用session。
- session會在一定時間內保存在服務器上。當訪問增多,會比較占用你服務器的性能
- 考慮到減輕服務器性能方面,應當使用COOKIE。
- 單個cookie保存的數據不能超過4K,很多瀏覽器都限制一個站點最多保存20個cookie。
- 所以個人建議:
- 將登陸信息等重要信息存放為SESSION
- 其他信息如果需要保留,可以放在COOKIE中
-
常見兼容性問題?
- png24位的圖片在iE6瀏覽器上出現背景,解決方案是做成PNG8.也可以引用一段腳本處理.
- 瀏覽器默認的margin和padding不同。解決方案是加一個全局的*{margin:0;padding:0;}來統一。
- IE6雙邊距bug:塊屬性標簽float后,又有橫行的margin情況下,在ie6顯示margin比設置的大。
- 浮動ie產生的雙倍距離(IE6雙邊距問題:在IE6下,如果對元素設置了浮動,同時又設置了margin-left或margin-right,margin值會加倍。)
-
box{ float:left; width:10px; margin:0 0 0 100px;}
- 這種情況之下IE會產生20px的距離,解決方案是在float的標簽樣式控制中加入
- _display:inline;將其轉化為行內屬性。(_這個符號只有ie6會識別)
- 漸進識別的方式,從總體中逐漸排除局部。
- 首先,巧妙的使用“\9”這一標記,將IE游覽器從所有情況中分離出來。
- 接着,再次使用“+”將IE8和IE7、IE6分離開來,這樣IE8已經獨立識別。
.bb{ background-color:#f1ee18;/*所有識別*/ .background-color:#00deff\9; /*IE6、7、8識別*/ +background-color:#a200ff;/*IE6、7識別*/ _background-color:#1e0bd1;/*IE6識別*/ }- 怪異模式問題:漏寫DTD聲明,Firefox仍然會按照標准模式來解析網頁,但在IE中會觸發怪異模式。為避免怪異模式給我們帶來不必要的麻煩,最好養成書寫DTD聲明的好習慣。現在可以使用html5推薦的寫法:
<doctype html>
數據結構與算法
- 判斷鏈表是否有環?
- 使用追趕的方法,設定兩個指針slow、fast,從頭指針開始,每次分別前進1步、2步。如存在環,則兩者相遇;如不存在環,fast遇到NULL退出。
- 輸出二叉樹的最小深度?
- 判斷左子樹或右子樹是否為空,若左子樹為空,則返回右子樹的深度,反之返回左子樹的深度,如果都不為空,則返回左子樹和右子樹深度的最小值。
- 棧和堆的區別?
- 棧區(stack)— 由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。
- 堆區(heap) — 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收。
- 堆(數據結構):堆可以被看成是一棵樹,如:堆排序;
- 棧(數據結構):一種先進后出的數據結構。
安全
- XSS和CSRF攻擊
- xss:比如在一個論壇發帖中發布一段惡意的JavaScript代碼就是腳本注入,如果這個代碼內容有請求外部服務器,那么就叫做XSS
- 寫一個腳本將cookie發送到外部服務器這就是xss攻擊但是沒有發生csrf
- 防范:對輸入內容做格式檢查 輸出的內容進行過濾或者轉譯
- CSRF:又稱XSRF,冒充用戶發起請求(在用戶不知情的情況下),完成一些違背用戶意願的請求 如惡意發帖,刪帖
- 比如在論壇發了一個刪帖的api鏈接 用戶點擊鏈接后把自己文章給刪了 這里就是csrf攻擊沒有發生xss
- 防范:驗證碼 token 來源檢測
- 常見web安全及防護原理
-
sql注入原理:就是通過把SQL命令插入到Web表單遞交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務器執行惡意的SQL命令。
- 總的來說有以下幾點:
1.永遠不要信任用戶的輸入,要對用戶的輸入進行校驗,可以通過正則表達式,或限制長度,對單引號和雙"-"進行轉換等。
2.永遠不要使用動態拼裝SQL,可以使用參數化的SQL或者直接使用存儲過程進行數據查詢存取。
3.永遠不要使用管理員權限的數據庫連接,為每個應用使用單獨的權限有限的數據庫連接。
4.不要把機密信息明文存放,請加密或者hash掉密碼和敏感的信息。
- 總的來說有以下幾點:
-
XSS原理及防范
- Xss(cross-site scripting)攻擊指的是攻擊者往Web頁面里插入惡意 html標簽或者javascript代碼。比如:攻擊者在論壇中放一個
- 看似安全的鏈接,騙取用戶點擊后,竊取cookie中的用戶私密信息;或者攻擊者在論壇中加一個惡意表單,
- 當用戶提交表單的時候,卻把信息傳送到攻擊者的服務器中,而不是用戶原本以為的信任站點。
-
XSS防范方法
- 首先代碼里對用戶輸入的地方和變量都需要仔細檢查長度和對”<”,”>”,”;”,”’”等字符做過濾;其次任何內容寫到頁面之前都必須加以encode,避免不小心把html tag 弄出來。這一個層面做好,至少可以堵住超過一半的XSS 攻擊。
- 首先,避免直接在cookie 中泄露用戶隱私,例如email、密碼等等。
- 其次,通過使cookie 和系統ip 綁定來降低cookie 泄露后的危險。這樣攻擊者得到的cookie 沒有實際價值,不可能拿來重放。
- 如果網站不需要再瀏覽器端對cookie 進行操作,可以在Set-Cookie 末尾加上HttpOnly 來防止javascript 代碼直接獲取cookie 。
- 盡量采用POST 而非GET 提交表單
-
XSS與CSRF有什么區別嗎?
- XSS是獲取信息,不需要提前知道其他用戶頁面的代碼和數據包。CSRF是代替用戶完成指定的動作,需要知道其他用戶頁面的代碼和數據包。
- 要完成一次CSRF攻擊,受害者必須依次完成兩個步驟:
- 登錄受信任網站A,並在本地生成Cookie。
- 在不登出A的情況下,訪問危險網站B。
-
CSRF的防御
- 服務端的CSRF方式方法很多樣,但總的思想都是一致的,就是在客戶端頁面增加偽隨機數。
- 通過驗證碼的方法
