前端基礎整理

1.前端基礎

1.1 prototype和 proto 的關係是什麼

.__proto__ ===.contructor.prototype //若是一個對象是經過Object.create函數構造出來的,那其__proto__就不必定是.constructor.prototype了 //屬性返回對建立此對象的數組函數的引用。 

1.2 meta viewport原理

layout viewport //某些網站會由於viewport太窄而顯示錯亂,瀏覽器就默認會把viewport設爲一個較寬的值,好比980px。寬度能夠經過 document.documentElement.clientWidth來獲取 visual viewport //表明瀏覽器可視區域的大小,寬度能夠經過 document.documentElement.innerWidth來獲取。 ideal viewport //是一個能完美適配移動設備的viewport,不一樣的設備有不一樣的ideal viewport。 

1.3 域名收斂是什麼

# 瀏覽器的併發限制: 瀏覽器對於同一域名下容許的併發請求數做了限制,一般同一域名下最大併發請求數爲6個; # 域名發散: 域名發散就是爲了突破瀏覽器對於同一域名併發請求數的限制,使用域名發散爲同一個服務申請多個域名,從而能夠必定程度上提升併發量;固然,因爲創建新的請求須要必定的代價,所以須要在域名發散與域名收斂間進行trade off,一般發散的域名個數爲2-4個; # 域名收斂: 域名收斂就是將靜態資源放在一個域名下不進行發散,這主要是爲了適應移動端的發展需求;一般DNS是一個開銷較大的操做,而移動端因爲網絡帶寬和實時性、資源等的限制,這些開銷對移動端的用戶體驗是致命的,所以須要進行域名收斂; 

1.4 float和display:inline-block;的區別

共性:
①inline-block: 是把一個元素的display設置爲塊狀內聯元素,意思就是說,讓一個元素的容器inline展現,而且裏面的內容block展現;inline屬性使元素內聯展現,內聯元素設置寬度無效,相鄰的inline元素會在一行顯示不換行,直到本行排滿爲止。block的元素始終會獨佔一行,呈塊狀顯示,可設置寬高。因此inline-block的元素就是寬高可設置,相鄰的元素會在一行顯示,直到本行排滿,也就是讓元素的容器屬性爲block,內容爲inline。 ②float: 設置元素的浮動爲左或者右浮動,當設置元素浮動時,相鄰元素會根據自身大小,排滿一行,若是父容器寬度不夠則會換行。當咱們設置了元素的浮動時,這個元素就脫離了文檔流,相鄰元素會呈環繞裝排列。 二者共同點是均可以實現元素在一行顯示,而且能夠自由設置元素大小。 區別: ①inline-block: 水平排列一行,即便元素高度不一,也會以高度最大的元素高度爲行高,即便高度小的元素周圍留空,也不回有第二行元素上浮補位。能夠設置默認的垂直對齊基線。 ②float: 讓元素脫離當前文檔流,呈環繞裝排列,如趕上行有空白,而當前元素大小能夠擠進去,這個元素會在上行補位排列。默認是頂部對齊。 

1.5 前端優化策略列舉

1、頁面級優化
    1. 減小 HTTP請求數 減小 HTTP請求數的主要途徑包括: (1). 從設計實現層面簡化頁面 (2). 合理設置 HTTP緩存 (3). 資源合併與壓縮 (4). CSS Sprites (5). Inline Images (6). Lazy Load Images 2. 將外部腳本置底(將腳本內容在頁面信息內容加載後再加載) 3. 異步執行 inline腳本(其實原理和上面是同樣,保證腳本在頁面內容後面加載。) 4. Lazy Load Javascript(只有在須要加載的時候加載,在通常狀況下並不加載信息內容。),能夠經過構建工具實現,好比配合路由加載 5. 將 CSS放在 HEAD中 6. 減小沒必要要的 HTTP跳轉 7. 避免重複的資源請求 2、代碼級優化 1.Reflow & Repaint reflow:幾乎是沒法避免的。如今界面上流行的一些效果,好比樹狀目錄的摺疊、展開(實質上是元素的顯 示與隱藏)等,都將引發瀏覽器的 reflow。鼠標滑過、點擊……只要這些行爲引發了頁面上某些元素的佔位面積、定位方式、邊距等屬性的變化,都會引發它內部、周圍甚至整個頁面的從新渲 染。一般咱們都沒法預估瀏覽器到底會 reflow 哪一部分的代碼,它們都彼此相互影響着。 repaint:若是隻是改變某個元素的背景色、文 字顏色、邊框顏色等等不影響它周圍或內部佈局的屬性,將只會引發瀏覽器 repaint(重繪)。repaint 的速度明顯快於 reflow (1):不要經過父級來改變子元素樣式,最好直接改變子元素樣式,改變子元素樣式儘量不要影響父元素和兄弟元素的大小和尺寸 (2):儘可能經過class來設計元素樣式,切忌用style 2.慎用 with with(obj){ p = 1}; 代碼塊的行爲其實是修改了代碼塊中的 執行環境 ,將obj放在了其做用域鏈的最前端,在 with代碼塊中訪問非局部變量是都是先從 obj上開始查找,若是沒有再依次按做用域鏈向上查找,所以使用 with至關於增長了做用域鏈長度。而每次查找做用域鏈都是要消耗時間的,過長的做用域鏈會致使查找性能降低。 3.避免使用 eval和 Function 4.減小做用域鏈查找(這方面設計到一些內容的相關問題) 做用域鏈查找問題,這一點在循環中是尤爲須要注意的問題。若是在循環中須要訪問非本做用域下的變量時請在遍歷以前用局部變量緩存該變量,並在遍歷結束後再重寫那個變量,這一點對全局變量尤爲重要,由於全局變量處於做用域鏈的最頂端,訪問時的查找次數是最多的。 5.數據訪問 Javascript中的數據訪問包括直接量 (字符串、正則表達式 )、變量、對象屬性以及數組,其中對直接量和局部變量的訪問是最快的,對對象屬性以及數組的訪問須要更大的開銷。 6.字符串拼接 在 Javascript中使用"+" 號來拼接字符串效率是比較低的,由於每次運行都會開闢新的內存並生成新的字符串變量,而後將拼接結果賦值給新變量。與之相比更爲高效的作法是使用數組的 join方法,即將須要拼接的字符串放在數組中最後調用其 join方法獲得結果。不過因爲使用數組也有必定的開銷,所以當須要拼接的字符串較多的時候能夠考慮用此方法。 7.CSS選擇符 8.Image壓縮 9.完整的前端優化還應該包括不少其餘的途徑,例如 CDN、 Gzip、多域名、無 Cookie服務器 

1.6 首屏、白屏時間如何計算

//load: 頁面上全部的資源(圖片,音頻,視頻等)被加載之後纔會觸發load事件
//DOMContentLoaded: 當文檔中沒有腳本時,瀏覽器解析完文檔便能觸發(ie6/7 onreadystatechange;ie<5 document.documentElement.doScroll("left")) 一般認爲瀏覽器開始渲染 <body> 標籤或者解析完 <head> 標籤的時刻就是頁面白屏結束的時間點。可是得考慮到css和js的阻塞。」加載是並行的,執行是串行的「的結果。html開始加載的時候,瀏覽器會將頁面外聯的css文件和js文件並行加載,若是一個文件還沒回來,它後面的代碼是不會執行的。剛剛咱們的demo,咱們阻塞了css文件幾秒,此時js文件由於並行已經加載回來,但因爲css文件阻塞住,因此後面 JsStartTime 的賦值語句是不執行的!當咱們放開阻塞,此時纔會運行到 JsStartTime 的賦值、js文件的解析、JsEndTime的賦值,因爲大頭時間加載早已完成,因此 JsEndTime 和 JsStartTime 的差值很是小。 

1.7 閉包

//閉包是函數和聲明該函數的詞法環境的組合,簡單的說就是經過函數保留詞法環境 function makeAdder(x) { return function(y) { return x + y; }; } var add5 = makeAdder(5); var add10 = makeAdder(10); console.log(add5(2)); // 7 console.log(add10(2)); // 12 //應用 for(var i=0;i<severalObj.length;i++){ (function(i){ severalObj[i].onclick=function(){......} })(i); } 

1.8 做用域鏈

做用域鏈: 當代碼在一個環境中執行時,會建立變量對象的一個做用域鏈。做用域鏈的用途是保證對執行環境有權訪問的全部變量和函數的有序訪問。做用域鏈的前端始終是當前執行的代碼所在環境的變量對象。若是這個環境是函數,則將其活動對象做爲變量對象。活動對象在最開始時只包含一個變量,即arguments對象。做用域鏈的下一個變量對象來自包含環境,而在下一個變量對象則來自下一個包含環境。這樣一直延續到全局執行環境;全局執行環境的變量對象始終都是做用域鏈中的最後一個對象。 執行環境(Execution Context): 每一個函數都有本身的執行環境。當執行流進入一個函數時,函數的環境就會被推入一個環境棧中。而在函數執行後,棧將其環境彈出,把控制權返回給以前的執行環境。 執行環境的創建分爲兩個階段:進入執行上下文(建立階段)和執行階段(激活/執行階段) (1)進入上下文階段:發生在函數調用時,但在執行具體代碼以前。具體完成建立做用域鏈;建立變量、函數和參數以及求this的值 (2)執行代碼階段:主要完成變量賦值、函數引用和解釋/執行其餘代碼 總的來講能夠將執行上下文看做是一個對象 變量對象(Variable Object):每個執行環境都對應一個變量對象,在該執行環境中定義的全部變量和函數都存放在其對應的變量對象中。 (1)進入執行上下文時,VO的初始化過程以下: 函數的形參:變量對象的一個屬性,其屬性名就是形參的名字,其值就是實參的值;對於沒有傳遞的參數,其值爲undefined; 函數聲明:變量對象的一個屬性,其屬性名和屬性值都是函數對象建立出來的,若是變量對象已經辦好了相同名字的屬性,則替換它的值 變量聲明:變量對象的一個屬性,其屬性名即爲變量名,其值爲undefined;若是變量名和已經聲明的函數名或者函數的參數名,則不會影響已經存在的屬性 (2)執行代碼階段,變量對象中的一些屬性undefined值將會肯定 這裏須要說明一下:函數表達式不包含在變量對象之中 活動對象:當函數被調用的時候,一個特殊的對象–活動對象將會被建立。這個對象中包含形參和arguments對象。活動對象以後會做爲函數上下文的變量對象來使用。換句話說,活動對象除了變量和函數聲明以外,它還存儲了形參和arguments對象。 

1.9 ajax如何實現、readyState五中狀態的含義

function createXMLHttpRequest() { var xmlHttp; // 適用於大多數瀏覽器,以及IE7和IE更高版本 try{ xmlHttp = new XMLHttpRequest(); } catch (e) { // 適用於IE6 try { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { // 適用於IE5.5,以及IE更早版本 try{ xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e){} } } return xmlHttp; }; 一、get請求 xmlHttp.open("GET", "/ajax_get/?a=1", true); //第一個參數爲請求方式,第二個參數爲請求的服務器地址,第三個參數表示是否異步請求,默認不傳值爲true xmlHttp.send(null); //get請求沒有請求體數據,可是須要發送null,不然會引發火狐瀏覽器沒法正常發送 二、post請求 xmlHttp.setRequestHeader(「Content-Type」, 「application/x-www-form-urlencoded」); //設置請求頭,form表單會默認這個鍵值對不設定,Web服務器會忽略請求體的內容。 xmlHttp.send(「username=yuan&password=123」) //設置請求體數據 三、狀態碼和響應內容只有在狀態4才能獲取到 xmlHttp.onreadystatechange = function() { if(xmlHttp.readyState == 4 && xmlHttp.status == 200) { alert(xmlHttp.responseText); } }; //狀態值 0:初始化未完成狀態,只是建立了XMLHttpRequest對象,還未調用open()方法; 1:請求已開始,open()方法已調用,但還沒調用send()方法; 2:請求發送完成狀態,send()方法已調用; 3:開始讀取服務器響應; 4:讀取服務器響應結束。onreadystatechange事件只會在除0之外的狀態下觸發。 

1.11 jsonp如何實現

function loadScript(url, func) { var head = document.head || document.getElementByTagName('head')[0]; var script = document.createElement('script'); script.src = url; script.onload = script.onreadystatechange = function() { if (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') { func(); script.onload = script.onreadystatechange = null; } }; head.insertBefore(script, 0); } window.baidu = { sug: function(data) { console.log(data); } } loadScript('http://suggestion.baidu.com/su?wd=w', function() { console.log('loaded') }); 

1.12怎麼處理跨域

一、經過jsonp跨域 二、CORS 主要工做是在服務端加上響應頭res.header("Access-Control-Allow-Origin", "xxx"),只要響應頭中包含了請求頭(Origin),就能夠實現跨域,至關於數據請求的決定權在於服務端是否贊成,所以CORS對於代碼的修改也只需修改服務端代碼便可。 三、document.domain + iframe (只有在主域相同的時候才能使用該方法) 四、location.hash + iframe 原理是利用location.hash來進行傳值。 假設域名a.com下的文件cs1.html要和cnblogs.com域名下的cs2.html傳遞信息。 1) cs1.html首先建立自動建立一個隱藏的iframe,iframe的src指向cnblogs.com域名下的cs2.html頁面 2) cs2.html響應請求後再將經過修改cs1.html的hash值來傳遞數據 3) 同時在cs1.html上加一個定時器,隔一段時間來判斷location.hash的值有沒有變化,一旦有變化則獲取獲取hash值 注:因爲兩個頁面不在同一個域下IE、Chrome不容許修改parent.location.hash的值,因此要藉助於a.com域名下的一個代理iframe 五、window.name + iframe 六、postMessage(HTML5中的XMLHttpRequest Level 2中的API) 七、web sockets (web sockets是一種瀏覽器的API,它的目標是在一個單獨的持久鏈接上提供全雙工、雙向通訊。(同源策略對web sockets不適用)) 

1.13 restful的method解釋

之前基本就用http的post和get。
restful就是讓你把delete put patch這些method給用起來,而不是經過post加上參數action=delete來實現刪除操做。 

1.14 get和post的區別

GET和POST本質上就是TCP連接,並沒有差異。可是因爲HTTP的規定和瀏覽器/服務器的限制,致使他們在應用過程當中體現出一些不一樣。 GET和POST還有一個重大區別,簡單的說:GET產生一個TCP數據包;POST產生兩個TCP數據包。對於GET方式的請求,瀏覽器會把http header和data一併發送出去,服務器響應200(返回數據); 而對於POST,瀏覽器先發送header,服務器響應100 continue,瀏覽器再發送data,服務器響應200 ok(返回數據)。 

1.15 事件模型解釋

javascript中有兩種事件模型:DOM0,DOM2
1. DOM0級事件模型 DOM0級事件模型是早期的事件模型,全部的瀏覽器都是支持的,並且其實現也是比較簡單。代碼以下: <p id = 'click'>click me</p> <script> document.getElementById('click').onclick = function(event){ alert(event.target); } </script> 這種事件模型就是直接在dom對象上註冊事件名稱,這段代碼就是在p標籤上註冊了一個onclick事件,在這個事件函數內部輸出點擊的目標。而解除事件則更加簡單,就是將null複製給事件函數,以下: document.getElementById('click'_).onclick = null; 由此咱們能夠知道dom0中,一個dom對象只能註冊一個同類型的函數,由於註冊多個同類型的函數的話,就會發生覆蓋,以前註冊的函數就會無效。 2. DOM2級事件模型 2.1 事件捕獲和事件冒泡(capture,bubble) 首先,IE8及如下是不支持這種事件模型的。假設咱們點擊了ID爲inner的div,那麼此時的事件流程就是,首先執行捕獲階段:document-html-body-div(outer)。而後執行冒泡階段:div(inner)-div(outer)-body-html-document。 2.2 DOM2級的註冊事件和解除事件 在DOM2級中使用attachEvent/addEventListener和removeEventListener來註冊和解除事件(IE8及以前版本不支持)。這種函數較之以前的方法好處是一個dom對象能夠註冊多個相同類型的事件,不會發生事件的覆蓋,會依次的執行各個事件函數。 addEventListener('事件名稱','事件回調','捕獲/冒泡')。第三個參數表明捕獲仍是冒泡,true表明捕獲事件,false表明冒泡事件。 btn1Obj.attachEvent("onclick",method1); detachEvent(event,function); 假如同時有捕獲和冒泡,事件捕獲比事件冒泡先執行。 

1.16 編寫一個元素拖拽的插件

1.17 編寫一個contextmenu的插件

1.18 編寫web端cookie的設置和獲取方法

//設置 document.cookie="userId=828; path=/;domain=cookieDomain;expires="+date.toGMTString(); document.cookie="str="+escape("I love ajax"); //獲取 function getCookie(name){ var strCookie=document.cookie; var arrCookie=strCookie.split("; "); for(var i=0;i<arrCookie.length;i++){ var arr=arrCookie[i].split("="); if(arr[0]==name)return arr[1]; } return ""; } //刪除,設置過時 function deleteCookie(name){ var date=new Date(); date.setTime(date.getTime()-10000); document.cookie=name+」=v; expires=」+date.toGMTString(); } 

1.19 兼容ie6的水平垂直居中

1.20 兼容ie的事件封裝

//事件處理兼容各類瀏覽器,採用能力檢測方法,所謂能力檢測,就是有能力就作,沒有能力就不作 //定義一個處理事件的對象,兼容各類瀏覽器,dom2級事件處理和ie事件,若是這兩個事件都不兼容,就採用dom0級處理 var eventUtil ={ addEvent:function(element,type,handler){ if (element.addEventListener) { //非IE瀏覽器採用dom2級事件處理,type爲事件類型如:click,handler爲事件處理函數,false表明事件採用冒泡處理模型,若是是true表明 採用捕獲型處理模型 //除了netbeans採用捕獲型處理模型,其餘都採用冒泡型處理模型 //若是是非IE瀏覽器添加事件爲:addEventListener element.addEventListener(type,handler,false); }else if (element.attachEvent) { //若是爲IE瀏覽器,添加事件採用 attachEvent element.attachEvent('on'+type,handler); }else{ element['on'+type] = handler; } }, removeEvent:function(element,type,handler){ if (element.removeEventListener) { //非IE瀏覽器採用dom2級事件處理,type爲事件類型如:click,handler爲事件處理函數,false表明事件採用冒泡處理模型,若是是true表明 採用捕獲型處理模型 //除了netbeans採用捕獲型處理模型,其餘都採用冒泡型處理模型 //若是是非IE瀏覽器添加事件爲:removeEventListener element.removeEventListener(type,handler,false); }else if (element.detachEvent) { //若是爲IE瀏覽器,添加事件採用 detachEvent element.detachEvent('on'+type,handler); }else{ //dom0級事件處理,若是刪除事件採用賦值null element['on'+type] = null; } }, getEvent:function(event){ //獲取事件自己 return event?event:window.event; }, getType:function(event){ //獲取事件類型 return event.type; }, getElement:function(event){ //獲取事件做用元素 return event.target || event.srcElement; }, preventDefault:function(event){ //阻止默認的事件行爲 if(event.preventDefault){ event.preventDefault(); }else{ event.returnValue = false; } }, stopProPagation:function(event){ //中止事件冒泡 if(event.stopProPagation){ event.stopProPagation(); }else{ event.cancelBubble = true; } } } 

1.21 h5和原生android的優缺點

1.22 編寫h5須要注意什麼

1. 交互上,慎用向右滑動的操做方式。 緣由:蘋果手機上,向右滑動容易觸發返回「上一級頁面」效果。 2. 交互上,慎用橫屏展現效果。 緣由:體驗上,須要用戶設備開啓屏幕旋轉功能,才能正常觀看,用戶操做成本高。 

對不一樣屏幕的手機,長寬比例不一,難以展現最佳的視覺效果。javascript

3. 視覺上,功能按鈕等,遠離頁面底部(大概128px,這個尺寸不是固定值) 4. 動畫上,序列幀壓縮小技巧,靜態的畫面,保存較高質量。中間運動的模糊狀態,大膽的壓低畫面質量吧。 緣由:壓縮體積,運動狀態就算有鋸齒也不明顯。 5. 重構上,視頻沒法自動播放,首次播放須要用戶點擊觸發。 

1.23 xss和crsf的原理以及怎麼預防

1.XSS成因歸納 :XSS其實就是Html的注入問題,攻擊者的輸入沒有通過嚴格的控制進入了數據庫,最終顯示給來訪的用戶,致使能夠在來訪用戶的瀏覽器裏以瀏覽用戶的身份執行Html代碼,數據流程以下:攻擊者的Html輸入—>web程序—>進入數據庫—>web程序—>用戶瀏覽器。 解決:使用轉義 2.CSRF:冒充用戶之手(模擬發請求) 解決:令牌來防止 CSRF 有如下幾點要注意: a.雖然請求令牌原理和驗證碼有類似之處,但不該該像驗證碼同樣,全局使用一個 Session Key。由於請求令牌的方法在理論上是可破解的,破解方式是解析來源頁面的文本,獲取令牌內容。若是全局使用一個 Session Key,那麼危險係數會上升。原則上來講,每一個頁面的請求令牌都應該放在獨立的 Session Key 中。咱們在設計服務器端的時候,能夠稍加封裝,編寫一個令牌工具包,將頁面的標識做爲 Session 中保存令牌的鍵。 b.在 ajax 技術應用較多的場合,由於頗有請求是 JavaScript 發起的,使用靜態的模版輸出令牌值或多或少有些不方便。但不管如何,請不要提供直接獲取令牌值的 API。這麼作無疑是鎖上了大門,卻又把鑰匙放在門口,讓咱們的請求令牌退化爲同步令牌。 c.第一點說了請求令牌理論上是可破解的,因此很是重要的場合,應該考慮使用驗證碼(令牌的一種升級,目前來看破解難度極大),或者要求用戶再次輸入密碼(亞馬遜、淘寶的作法)。但這兩種方式用戶體驗都很差,因此須要產品開發者權衡。 d.不管是普通的請求令牌仍是驗證碼,服務器端驗證過必定記得銷燬。忘記銷燬用過的令牌是個很低級可是殺傷力很大的錯誤。咱們學校的選課系統就有這個問題,驗證碼用完並未銷燬,故只要獲取一次驗證碼圖片,其中的驗證碼能夠在屢次請求中使用(只要再也不次刷新驗證碼圖片),一直用到。 

1.24 css優先級

1.25 如何實現點擊radio的文字描述控制radio的狀態(經過label實現)

1.26 delegate如何實現

1.27 使用Promise封裝簡單Ajax方法

1.GETcss

function getJSON (url) { return new Promise( (resolve, reject) => { var xhr = new XMLHttpRequest() xhr.open('GET', url, true) xhr.onreadystatechange = function () { if (this.readyState === 4) { if (this.status === 200) { resolve(this.responseText, this) } else { var resJson = { code: this.status, response: this.response } reject(resJson, this) } } } xhr.send() }) } 

2.POSThtml

function postJSON(url, data) { return new Promise( (resolve, reject) => { var xhr = new XMLHttpRequest() xhr.open("POST", url, true) xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhr.onreadystatechange = function () { if (this.readyState === 4) { if (this.status === 200) { resolve(JSON.parse(this.responseText), this) } else { var resJson = { code: this.status, response: this.response } reject(resJson, this) } } } xhr.send(JSON.stringify(data)) }) } 

2.框架原理

2.1 angularjs

2.1.1 angular的directive怎麼寫

2.1.2 angular的髒檢查(雙向綁定)是如何實現的

2.1.3 依賴注入如何實現

2.1.4 scope如何實現

2.1.5 $parse模塊如何實現(主要本身寫了一個相似的庫)

2.2 react

2.2.1 react在setState後發生了什麼(直接說了setState源碼)

在代碼中調用setState函數以後,React 會將傳入的參數對象與組件當前的狀態合併,而後觸發所謂的調和過程(Reconciliation)。通過調和過程,React 會以相對高效的方式根據新的狀態構建 React 元素樹而且着手從新渲染整個UI界面。在 React 獲得元素樹以後,React 會自動計算出新的樹與老樹的節點差別,而後根據差別對界面進行最小化重渲染。在差別計算算法中,React 可以相對精確地知道哪些位置發生了改變以及應該如何改變,這就保證了按需更新,而不是所有從新渲染。 setState歷來不負責更新操做。它的工做只是把state,和callback放進序列,而且把要更新的組件放到dirtyComponents序列 

還記得嗎?咱們還在ReactDefalutBatchingStragy的事務中,perform執行完了,還要執行close。 真正執行更新方法的是close裏面的flushBatchedUpdates。前端

2.2.2 redux解釋

2.2.3 對react有什麼瞭解(直接說了react中虛擬dom內部表示,mount過程源碼和同步過程源碼)

2.2.4 jsBridge

2.2.5 如何說服對方使用jsBridge

2.2.6 diff算法

傳統 diff 算法的複雜度爲 O(n^3),顯然這是沒法知足性能要求的。React 經過制定大膽的策略,將 O(n^3) 複雜度的問題轉換成 O(n) 複雜度的問題。 diff 策略: tree diff Web UI 中 DOM 節點跨層級的移動操做特別少,能夠忽略不計。 component diff 擁有相同類的兩個組件將會生成類似的樹形結構,擁有不一樣類的兩個組件將會生成不一樣的樹形結構。 element diff 對於同一層級的一組子節點,它們能夠經過惟一 id 進行區分。 

2.3 requirejs

2.3.1 amd和cmd區別,怎麼了解到這些區別的,是不是去看了規範

AMD 是 RequireJS 在推廣過程當中對模塊定義的規範化產出。
CMD 是 SeaJS 在推廣過程當中對模塊定義的規範化產出。
相同之處
    RequireJS 和 Sea.js 都是模塊加載器,倡導模塊化開發理念,核心價值是讓 JavaScript 的模塊化開發變得簡單天然。 不一樣之處 二者的主要區別以下: 1.定位有差別。RequireJS 想成爲瀏覽器端的模塊加載器,同時也想成爲 Rhino / Node 等環境的模塊加載器。Sea.js 則專一於 Web 瀏覽器端,同時經過 Node 擴展的方式能夠很方便跑在 Node 環境中。 2.遵循的規範不一樣。RequireJS 遵循 AMD(異步模塊定義)規範,Sea.js 遵循 CMD (通用模塊定義)規範。規範的不一樣,致使了二者 API 不一樣。Sea.js 更貼近 CommonJS Modules/1.1 和 Node Modules 規範。 3.推廣理念有差別。RequireJS 在嘗試讓第三方類庫修改自身來支持 RequireJS,目前只有少數社區採納。Sea.js 不強推,採用自主封裝的方式來「海納百川」,目前已有較成熟的封裝策略。 4.對開發調試的支持有差別。Sea.js 很是關注代碼的開發調試,有 nocache、debug 等用於調試的插件。RequireJS 無這方面的明顯支持。 5.插件機制不一樣。RequireJS 採起的是在源碼中預留接口的形式,插件類型比較單一。Sea.js 採起的是通用事件機制,插件類型更豐富。 

2.3.2 requirejs那些常常用的方法,而後對其進行解釋

2.4 weex

2.4.1 weex實現大體原理(只寫過demo,面試管很好沒有難爲我,只問了這一個問題)

3.http協議

3.1 accept是什麼,怎麼用

1.Accept屬於請求頭, Content-Type屬於實體頭。 2.Accept表明發送端(客戶端)但願接受的數據類型。 好比:Accept:text/xml; 表明客戶端但願接受的數據類型是xml類型 

3.2 http協議狀態碼,302和303的區別

3.4 前端緩存如何實現、etag如何實現、etag和cache-control的max-age的優先級哪一個比較高以及爲何、cache-control和expire優先級哪一個比較高以及爲何

1)Expires是http1.0提出的一個表示資源過時時間的header,它描述的是一個絕對時間,由服務器返回,用GMT格式的字符串表示,如:Expires:Thu, 31 Dec 2016 23:55:55 GMT,
2)Cache-Control描述的是一個相對時間,在進行緩存命中的時候,都是利用客戶端時間進行判斷,因此相比較Expires,Cache-Control的緩存管理更有效,安全一些。 3)Last-Modified/If-Modified-Since:Last-Modified/If-Modified-Since要配合Cache-Control使用。 Last-Modified:標示這個響應資源的最後修改時間。web服務器在響應請求時,告訴瀏覽器資源的最後修改時間。 If-Modified-Since:當資源過時時(強緩存失效),發現資源具備Last-Modified聲明,則再次向web服務器請求時帶上頭 If-Modified-Since,表示請求時間。web服務器收到請求後發現有頭If-Modified-Since 則與被請求資源的最後修改時間進行比對。若最後修改時間較新,說明資源又被改動過,則響應整片資源內容(寫在響應消息包體內),HTTP 200;若最後修改時間較舊,說明資源無新修改,則響應HTTP 304 (無需包體,節省瀏覽),告知瀏覽器繼續使用所保存的cache。 4)Etag/If-None-Match:Etag/If-None-Match也要配合Cache-Control使用。 Etag:web服務器響應請求時,告訴瀏覽器當前資源在服務器的惟一標識(生成規則由服務器決定)。Apache中,ETag的值,默認是對文件的索引節(INode),大小(Size)和最後修改時間(MTime)進行Hash後獲得的。 If-None-Match:當資源過時時(使用Cache-Control標識的max-age),發現資源具備Etage聲明,則再次向web服務器請求時帶上頭If-None-Match (Etag的值)。web服務器收到請求後發現有頭If-None-Match 則與被請求資源的相應校驗串進行比對,決定返回200或304。 

4.node

4.1 Buffer模塊是幹什麼的

在 ECMAScript 2015 (ES6) 引入 TypedArray 以前,JavaScript 語言沒有讀取或操做二進制數據流的機制。 Buffer 類被引入做爲 Node.js API 的一部分,使其能夠在 TCP 流或文件系統操做等場景中處理二進制數據流。 

4.2 Stream是什麼,使用的兩種模式

流(stream)在 Node.js 中是處理流數據的抽象接口(abstract interface)。 stream 模塊提供了基礎的 API 。使用這些 API 能夠很容易地來構建實現流接口的對象。 在 flowing 模式下, 可讀流自動從系統底層讀取數據,並經過 EventEmitter 接口的事件儘快將數據提供給應用。 在 paused 模式下,必須顯式調用 stream.read() 方法來從流中讀取數據片斷。 

4.3 http模塊如何將異步處理方式實現成同步處理方式,具體解析請參考http模塊如何將異步處理轉成同步處理

const http = require("http"); const net = require("net"); // 保存請求的隊列,每一個元素都是一個socket let watingQueue = []; // 當前處理的請求 let curtSocket = null; let count = 0; // 創建一個http服務器 let httpServer = http.createServer(function (req, res) { // 延遲一秒中回覆 setTimeout(function () { res.end(`request: ${++count}`, "utf8"); }, 1000); res.on("finish", function () { curtSocket = null; // 一個請求結束了,處理下一個請求 dealRequest(); }); }); // 創建一個tcp的服務器(http協議是創建在tcp協議上的) net.createServer(function (socket) { // 將請求壓入列隊 enqueueSocket(socket); // 處理請求(若是如今真在處理的請求,不作任何處理) dealRequest(); }).listen(4000); function enqueueSocket (socket) { watingQueue.push(socket); } function dealRequest () { if (curtSocket != null || watingQueue.length <= 0) { return; } curtSocket = watingQueue.shift(); httpServer.emit("connection", curtSocket); } 

5.其餘問題

5.1 utf8和gbk的區別

UTF-8 (8-bit Unicode Transformation Format) 是一種針對Unicode的可變長度字符編碼,又稱萬國碼,它包含全世界全部國家須要用到的字符,是國際編碼,通用性強,是用以解決國際上字符的一種多字節編碼。由Ken Thompson於1992年建立。UTF-8用1到4個字節編碼UNICODE字符,它對英文使用8位/8Bit(即1個字節/1Byte),中文使用24位/24Bit(3個字節/3Byte)來編碼。用在網頁上能夠同一頁面顯示中文簡體繁體及其它語言(如日文,韓文)。 GBK (Chinese Internal Code Specification) 是漢字編碼標準之一,全稱《漢字內碼擴展規範》,中華人民共和國全國信息技術標準化技術委員會1995年12月1日製訂,國家技術監督局標準化司、電子工業部科技與質量監督司1995年12月15日聯合以技監標函1995 229號文件的形式,將它肯定爲技術規範指導性文件。 

GBK是國家標準GB2312基礎上擴容後兼容GB2312的標準(GB2312共收錄了7445個字符,包括6763個漢字和682個其它符號;GBK共收錄了27484個漢字,同時還收錄了藏文、蒙文、維吾爾文等主要的少數民族文字)。GBK的文字編碼是用雙字節來表示的,即不論中、英文字符均使用雙字節來表示(注意,GB系列編碼是利用了字節中的最高位和ASCII編碼區分的,能夠和ASCII碼混用。因此全角模式下英文是2字節,半角模式英文仍是1字節)。爲了區分中文,將其最高位都設定成1。GBK包含所有中文字符,是國家編碼,通用性比UTF8差,不過UTF8佔用的數據庫比GBD大。java

簡單概況就是:
UTF-8英文1字節中文3字節,在編碼效率和編碼安全性之間作了平衡,適合網絡傳輸,是理想的中文編碼方式. GBK英文1字節(半角1字節,全角2字節),中文2字節,GBK的範圍比GB2312廣,GBK兼容GB2312。
相關文章
相關標籤/搜索