7、React數據流javascript
8、爲何虛擬DOM會提升性能 www.zhihu.com/question/29… 虛擬DOM至關於在js和真實dom中間加了一個緩存,利用dom diff算法避免了沒有必要的doom操做,從而提升性能 具體實現步驟: ·用JavaScript對象結構表示DOM樹的結構;而後用這個樹構建一個真正的DOM樹,插到文檔中 ·當狀態變動的時候,從新構造一棵樹的對象樹,而後用新的樹和舊的樹進行對比,記錄兩棵樹差別 ·把2所記錄的差別應用到步驟1所構建的真正的DOM樹上,試圖就更新了。css
9、diff算法 1.把樹形結構按照層級分解,只比較同級元素 2.給列表結構的每一個單元添加key屬性,方便比較。在實際代碼中,會對新舊兩棵樹進行一個深度優先的遍歷,這樣每一個節點都會有一個標記 3.在深度優先遍歷的時候,每遍歷到一個節點就把該節點和新的樹進行對比。若是有差別的話就記錄到一個對象裏面 Vritual DOM 算法主要實現上面步驟的三個函數:element, diff, patch。而後就能夠實際的進行使用 react只會匹配相同的class的component(這裏的class指的是組件的名字) 合併操做,條用component的setState方法的時候,React將其標記爲dirty.到每個時間循環借宿,React檢查全部標記dirty的component從新繪製 4.選擇性子樹渲染。能夠重寫shouldComponentUpdate提升diff的性能html
10、super前端
11、簡述下flux的思想 flux的最大特色,就是數據的‘單向流動’ 1.用戶訪問View 2.View發出用戶的Action 3.Dispatcher收到Action,要求state進行相應的更新 4.store更新後,發出一個‘change’事件後,更新頁面java
12、reac性能優化是哪一個週期函 shouldComponentUpdate 這個方法用來判斷是否須要調用render方法從新描繪dom.由於dom的描繪很是消耗性能, 若是咱們在shouldComponentUpdate方法中可以寫出更優化的dom diff算法,能夠極大的提升性能node
十3、react怎麼劃分業務組件和技術組件 根據組件的職責一般把組件分爲UI組件和容器組件 UI組件負責UI的呈現,容器組件負責管理數據和邏輯 二者經過React-redux提供connect方法聯繫起來react
十4、setState setState經過一個隊列機制實現state更新,當執行setState時,會將須要更新的state很後放入狀態隊列 而不會當即更新this.state,隊列機制能夠高效地批量更新state。若是不經過setState而直接修改this.state的值 那麼該state將不會被放入狀態隊列中。當下次調用setState並對狀態隊列進行合併時,就會忽略以前修改的state,形成不可預知的錯誤webpack
同時,也利用了隊列機制實現了setState的異步更新,避免了頻繁的重複更新state
同步更新state:
setState 函數並不會阻塞等待狀態更新完畢,所以 setNetworkActivityIndicatorVisible 有可能先於數據渲染完畢就執行。第二個參數是一個回調函數,在setState的異步操做結束而且組件已經從新渲染的時候執行
也就是說,咱們能夠經過這個回調來拿到更新的state的值,實現代碼的同步
例子:componentDidMount() {
fetch('https://test.com')
.then((res) => res.json())
.then(
複製代碼
(data) => { this.setState({ data:data });web
StatusBar.setNetworkActivityIndicatorVisible(false);
}
性能優化
複製代碼
1、webpack打包文件體積過大?(最終打包爲一個js文件) 1.異步加載模塊 2.提取第三庫 3.代碼壓縮 4.去除沒必要要的插件ajax
如何優化webpack構建的性能 1、減小代碼體積 1.使用CommonsChunksPlugin 提取多個chunk之間的通用模塊,減小整體代碼體積 2.把部分依賴轉移到CDN上,避免每次編譯過程都由Webpack處理 3.對一些組件庫採用按需加載,避免無用的代碼 2、減小目錄檢索範圍 ·在使用loader的時候,經過制定exclude和include選項,減小loader遍歷的目錄範圍,從而加快webpack編譯速度
3、減小檢索路經:resolve.alias能夠配置webpack模塊解析的別名,對於比較深的解析路經,能夠對其配置alias
複製代碼
2、咱們把開發中的全部資源(圖片,js、css文件)都當作模塊,經過loader和plugins來對資源進行處理,打包成符合生產環節部署的前端資源。
3、移動端的性能優化 一、首屏加載和按需加載,懶加載 二、資源預加載 三、圖片壓縮處理,使用base64內嵌圖片 四、合理緩存dom對象 五、使用touchstart代替click(click 300毫秒的延遲) 六、利用transform:translateZ(0),開啓硬件GUP加速 七、不濫用web字體,不濫用float(佈局計算消耗性能),減小font-size聲明 八、使用viewport固定屏幕渲染,加速頁面渲染內容 九、儘可能使用事件代理,避免直接事件綁定
4、Vue的SPA 如何優化加載速度 1.減小入口文件體積 2.靜態資源本地緩存 3.開啓Gzip壓縮 4.使用SSR,nuxt.js
5、移動端300ms延遲 由來:300毫米延遲解決的是雙擊縮放。雙擊縮放,手指在屏幕快速點擊兩次。safari瀏覽器就會將網頁縮放值原始比例。 因爲用戶能夠雙擊縮放或者是滾動的操做,當用戶點擊屏幕一次以後,瀏覽器並不會判斷用戶確實要打開至這個連接,仍是想要進行雙擊操做 因次,safair瀏覽器就會等待300ms,用來判斷用戶是否在次點擊了屏幕 解決方案:1.禁用縮放,設置meta標籤 user-scalable=no 2.fastclick.js 原理:FastClick的實現原理是在檢查到touchend事件的時候,會經過dom自定義事件當即 發出click事件,並把瀏覽器在300ms以後真正的click事件阻止掉 fastclick.js還能夠解決穿透問題
6、頁面的重構;在不改變外部行爲的前提下,簡化結構、添加可讀性
服務器端
複製代碼
1、狀態碼:
2XX(成功處理了請求狀態)
200 服務器已經成功處理請求,並提供了請求的網頁
201 用戶新建或修改數據成功
202 一個請求已經進入後臺
204 用戶刪除成功
3XX(每次請求使用的重定向不要超過5次)
304 網頁上次請求沒有更新,節省帶寬和開銷
4XX(表示請求可能出錯,妨礙了服務器的處理)
400 服務器不理解請求的語法
401 用戶沒有權限(用戶名,密碼輸入錯誤)
403 用戶獲得受權(401相反),可是訪問被禁止
404 服務器找不到請求的網頁,
5XX(表示服務器在處理請求的時候發生內部錯誤)
500 服務器遇到錯誤,沒法完成請求
503 服務器目前沒法使用(超載或停機維護)
複製代碼
2、304的緩存原理(添加Etag標籤.last-modified) 304 網頁上次請求沒有更新,節省帶寬和開銷 1.服務器首先產生Etag,服務器可在稍後使用它來判斷頁面是否被修改。本質上,客戶端經過該記號傳回服務器要求服務器驗證(客戶端)緩存) 2.304是 HTTP的狀態碼,服務器用來標識這個文件沒有被修改,不返回內容,瀏覽器接受到這個狀態碼會去去找瀏覽器緩存的文件 3.流程:客戶端請求一個頁面A。服務器返回頁面A,並在A上加一個Tage客服端渲染該頁面,並把Tage也存儲在緩存中。客戶端再次請求頁面A 並將上次請求的資源和ETage一塊兒傳遞給服務器。服務器檢查Tage.而且判斷出該頁面自上次客戶端請求以後未被修改。直接返回304
last-modified: 客服端請求資源,同時有一個last-modified的屬性標記此文件在服務器最後修改的時間
客服端第二次請求此url時,根據http協議。瀏覽器會向服務器發送一個If-Modified-Since報頭,
詢問該事件以後文件是否被修改,沒修改返回304
有了Last-Modified,爲何還要用ETag?
一、由於若是在一秒鐘以內對一個文件進行兩次更改,Last-Modified就會不正確(Last—Modified不能識別秒單位的修改)
二、某些服務器不能精確的獲得文件的最後修改時間
三、一些文件也行會週期新的更改,可是他的內容並不改變(僅僅改變修改的事件),這個時候咱們並不但願客戶端認爲文件被修改,而從新Get
ETag,爲何還要用Last-Modified?
一、二者互補,ETag的判斷的缺陷,好比一些圖片等靜態文件的修改
二、若是每次掃描內容都生成ETag比較,顯然要比直接比較修改時間慢的多。
ETag是被請求變量的實體值(文件的索引節,大小和最後修改的時間的Hash值)
一、ETag的值服務器端對文件的索引節,大小和最後的修改的事件進行Hash後獲得的。
複製代碼
3、get/post的區別 1.get數據是存放在url以後,以?分割url和傳輸數據,參數之間以&相連; post方法是把提交的數據放在http包的Body中 2.get提交的數據大小有限制,(由於瀏覽器對url的長度有限制),post的方法提交的數據沒有限制 3.get須要request.queryString來獲取變量的值,而post方式經過request.from來獲取變量的值 4.get的方法提交數據,會帶來安全問題,好比登陸一個頁面,經過get的方式提交數據,用戶名和密碼就會出如今url上
4、http協議的理解 1.超文本的傳輸協議,是用於從萬維網服務器超文本傳輸到本地資源的傳輸協議 2.基於TCP/IP通訊協議來傳遞數據(HTML,圖片資源) 3.基於運用層的面向對象的協議,因爲其簡潔、快速的方法、適用於分佈式超媒體信息系統 4.http請求信息request: 請求行(request line)、請求頭部(header),空行和請求數據四部分構成
請求行,用來講明請求類型,要訪問的資源以及所使用的HTTP版本.
請求頭部,用來講明服務器要使用的附加信息
空行,請求頭部後面的空行是必須的
請求數據也叫主體,能夠添加任意的其餘數據。
5.http相應信息Response
狀態行、消息報頭、空行和響應正文
狀態行,由HTTP協議版本號, 狀態碼, 狀態消息 三部分組成
消息報頭,用來講明客戶端要使用的一些附加信息
空行,消息報頭後面的空行是必須的
響應正文,服務器返回給客戶端的文本信息。
複製代碼
5、http和https https:是以安全爲目標的HTTP通道,簡單講是HTTP的安全版本,經過SSL加密 http:超文本傳輸協議。是一個客服端和服務器端請求和應答的標準(tcp),使瀏覽器更加高效,使網絡傳輸減小
5、http1.0 1.1 2.0的區別 長鏈接:HTTP1.0須要使用keep-alive參數來告知服務器創建一個長鏈接,而HTP1.1默認支持長鏈接 節約寬帶:HTTP1.1支持只發送一個header信息(不帶任何body信息) host域(設置虛擬站點,也就是說,web server上的多個虛擬站點能夠共享同一個ip端口):HTTP1.0沒有host域
1.http2採用的二進制文本傳輸數據,而非http1文本格式,二進制在協議的解析和擴展更好
2.數據壓縮:對信息頭採用了HPACK進行壓縮傳輸,節省了信息頭帶來的網絡流量
3.多路複用:一個鏈接能夠併發處理多個請求
4.服務器推送:咱們對支持HTTP2.0的web server請求數據的時候,服務器會順便把一些客戶端須要的資源一塊兒推送到客戶端,省得客戶端再次建立鏈接發送請求到服務器端獲取。這種方式很是合適加載靜態資源
複製代碼
7、web緩存 1.web緩存就是存在於客戶端與服務器之間的一個副本、當你第一個發出請求後,緩存根據請求保存輸出內容的副本 2.緩存的好處 (1)減小沒必要要的請求 (2)下降服務器的壓力,減小服務器的消耗 (3)下降網絡延遲,加快頁面打開速度(直接讀取瀏覽器的數據)
8、常見的web安全及防禦原理 1.sql注入原理:通郭sql命令插入到web表單遞交或者輸入活命,達到欺騙服務器執行的惡意sql命令 防範:1.對用戶輸入進行校驗 2.不適用動態拼接sql 2.XSS(跨站腳本攻擊):往web頁面插入惡意的html標籤或者js代碼。 舉例子:在論壇放置一個看是安全的連接,竊取cookie中的用戶信息 防範:1.儘可能採用post而不使用get提交表單 2.避免cookie中泄漏用戶的隱式 3.CSRF(跨站請求假裝):經過假裝來自受信任用戶的請求 舉例子:黃軼老師的webapp音樂請求數據就是利用CSRF跨站請求假裝來獲取QQ音樂的數據 防範:在客服端頁面增長僞隨機數,經過驗證碼 XSS和CSRF的區別: 1.XSS是獲取信息,不須要提早知道其餘用戶頁面的代碼和數據包 2.CSRF代替用戶完成指定的動做,須要知道其餘頁面的代碼和數據包
9、CDN(內容分發網絡) 1.儘量的避開互聯網有可能影響數據傳輸速度和穩定性的瓶頸和環節。使內容傳輸的更快更穩定。 2.關鍵技術:內容存儲和分發技術中 3.基本原理:普遍採用各類緩存服務器,將這些緩存服務器分佈到用戶訪問相對的地區或者網絡中。當用戶訪問網絡時利用全局負載技術 將用戶的訪問指向距離最近的緩存服務器,由緩存服務器直接相應用戶的請求(全局負載技術)
10、TCP三次握手 (客服端和服務器端都須要確認各自可收發) 客服端發c起請求鏈接服務器端s確認,服務器端也發起鏈接確認客服端確認。 第一次握手:客服端發送一個請求鏈接,服務器端只能確認本身能夠接受客服端發送的報文段 第二次握手: 服務端向客服端發送一個連接,確認客服端收到本身發送的報文段 第三次握手: 服務器端確認客服端收到了本身發送的報文段
11、從輸入url到獲取頁面的完整過程 blog.csdn.net/samjustin1/… 1.查詢NDS(域名解析),獲取域名對應的IP地址 查詢瀏覽器緩存 2.瀏覽器與服務器創建tcp連接(三次握手) 3.瀏覽器向服務器發送http請求(請求和傳輸數據) 4.服務器接受到這個請求後,根據路經參數,通過後端的一些處理生成html代碼返回給瀏覽器 5.瀏覽器拿到完整的html頁面代碼開始解析和渲染,若是遇到外部的css或者js,圖片同樣的步驟 6.瀏覽器根據拿到的資源對頁面進行渲染,把一個完整的頁面呈現出來
12、瀏覽器渲染原理及流程 DOM -> CSSOM -> render -> layout -> print 流程:解析html以及構建dom樹 -> 構建render樹 -> 佈局render樹 -> 繪製render樹 概念:1.構建DOM樹: 渲染引擎解析HTML文檔,首先將標籤轉換成DOM樹中的DOM node(包括js生成的標籤)生成內容樹 2.構建渲染樹: 解析對應的css樣式文件信息(包括js生成的樣式和外部的css) 3.佈局渲染樹:從根節點遞歸調用,計算每個元素的大小,位置等。給出每一個節點所在的屏幕的精準位置 4.繪製渲染樹:遍歷渲染樹,使用UI後端層來繪製每個節點
重繪:當盒子的位置、大小以及其餘屬性,例如顏色、字體大小等到肯定下來以後,瀏覽器便把這些顏色都按照各自的特性繪製一遍,將內容呈如今頁面上
觸發重繪的條件:改變元素外觀屬性。如:color,background-color等
重繪是指一個元素外觀的改變所觸發的瀏覽器行爲,瀏覽器會根據元素的新屬性從新繪製,使元素呈現新的外觀
注意:table及其內部元素須要屢次計算才能肯定好其在渲染樹中節點的屬性值,比同等元素要多發時間,要儘可能避免使用table佈局
重排(重構/迴流/reflow): 當渲染書中的一部分(或所有)由於元素的規模尺寸,佈局,隱藏等改變而須要從新構建,這就是迴流。
每一個頁面都須要一次迴流,就是頁面第一次渲染的時候
重排必定會影響重繪,可是重繪不必定會影響重排
複製代碼
十3、爲何css放在頂部而js寫在後面 1.瀏覽器預先加載css後,能夠沒必要等待HTML加載完畢就能夠渲染頁面了 2.其實HTML渲染並不會等到徹底加載完在渲染頁面,而是一邊解析DOM一邊渲染。 3.js寫在尾部,主要是由於js主要扮演事件處理的功能,一方面不少操做是在頁面渲染後才執行的。另外一方面能夠節省加載時間,使頁面可以更加的加載,提升用戶的良好體驗
可是隨着JS技術的發展,JS也開始承擔頁面渲染的工做。好比咱們的UI其實能夠分被對待,把渲染頁面的js放在前面,時間處理的js放在後面
複製代碼
十4、存儲方式與傳輸方式 1.indexBD: 是h5的本地存儲庫,把一些數據存儲到瀏覽器中,沒網絡,瀏覽器能夠從這裏讀取數據,離線運用。5m 2.Cookie: 經過瀏覽器記錄信息確認用戶身份,最大4kb,這也就限制了傳輸的數據,請求的性能會受到影響 3.Session: 服務器端使用的一種記錄客戶狀態的機制(session_id存在set_cookie發送到客服端,保存爲cookie) 4.localStroage: h5的本地存儲,數據永久保存在客服端
一、cookie,sessionStorage,localStorage是存放在客戶端,session對象數據是存放在服務器上
實際上瀏覽器和服務器之間僅需傳遞session id便可,服務器根據session-id找到對應的用戶session對象
session存儲數據更安全一些,通常存放用戶信息,瀏覽器只適合存儲通常的數據
二、cookie數據始終在同源的http請求中攜帶,在瀏覽器和服務器來回傳遞,裏面存放着session-id
sessionStorage,localStorage僅在本地保存
三、大小限制區別,cookie數據不超過4kb,localStorage在谷歌瀏覽中2.6MB
四、數據有效期不一樣,cookie在設置的(服務器設置)有效期內有效,無論窗口和瀏覽器關閉
sessionStorage僅在當前瀏覽器窗口關閉前有效,關閉即銷燬(臨時存儲)
localStorage始終有效
複製代碼
SessionStorage和localStorage區別: 1.sessionStorage用於本地存儲一個會話(session)中的數據,這些數據只有在用一個會話的頁面中才能被訪問(也就是說在第一次通訊過程當中) 而且在會話結束後數據也隨之銷燬,不是一個持久的本地存儲,會話級別的儲存 2.localStorage用於持久化的本地存儲,除非主動刪除數據,不然不會過時
token、cookie、session三者的理解???!!! 一、token就是令牌,好比你受權(登陸)一個程序時,他就是個依據,判斷你是否已經受權該軟件(最好的身份認證,安全性好,且是惟一的) 用戶身份的驗證方式
二、cookie是寫在客戶端一個txt文件,裏面包括登陸信息之類的,這樣你下次在登陸某個網站,就會自動調用cookie自動登陸用戶名
服務器生成,發送到瀏覽器、瀏覽器保存,下次請求再次發送給服務器(存放着登陸信息)
三、session是一類用來客戶端和服務器之間保存狀態的解決方案,會話完成被銷燬(表明的就是服務器和客戶端的一次會話過程)
cookie中存放着sessionID,請求會發送這個id。sesion由於request對象而產生。
基於Token的身份驗證:(最簡單的token: uid用戶惟一的身份識別 + time當前事件戳 + sign簽名)
一、用戶經過用戶名和密碼發送請求
二、服務器端驗證
三、服務器端返回一個帶簽名的token,給客戶端
四、客戶端儲存token,而且每次用於發送請求
五、服務器驗證token而且返回數據
每一次請求都須要token
cookie與session區別
一、cookie數據存放在客戶的瀏覽器上,session數據放在服務器上。
二、cookie不是很安全,別人能夠分析存放在本地的COOKIE並進行COOKIE欺騙考慮到安全應當使用session。
三、session會在必定時間內保存在服務器上。當訪問增多,會比較佔用你服務器的性能考慮到減輕服務器性能方面,應當使用COOKIE。
四、單個cookie保存的數據不能超過4K,不少瀏覽器都限制一個站點最多保存20個cookie。
session與token區別
一、session認證只是把簡單的User的信息存儲Session裏面,sessionID不可預測,一種認證手段。只存在服務端,不能共享到其餘的網站和第三方App
二、token是oAuth Token,提供的是認證和受權,認證針對用戶,受權是針對App,目的就是讓某APP有權訪問某用戶的的信息。Token是惟一的,
token不能轉移到其餘的App,也不能轉到其餘用戶上。(適用於App)
三、session的狀態是存在服務器端的,客戶端只存在session id, Token狀態是存儲在客戶端的
Cookie的弊端有哪些???(優點:保存客戶端數據,分擔了服務器存儲的負擔)
一、數量和長度的限制。每一個特定的域名下最多生成20個cookie(chorme和safari沒有限制)
二、安全性問題。
設計模式
複製代碼
1、觀察者模式:juejin.im/post/5a14e9… juejin.im/post/5af05d… 在軟件開發設計中是一個對象(subject),維護一系列依賴他的對象(observer),當任何狀態發生改變自動通知他們。強依賴關係 簡單理解:數據發生改變時,對應的處理函數就會自動執行。一個Subjet,用來維護Observers,爲某些event來通知(notify)觀察者
2、發佈-訂閱者 有一個信息中介,過濾 耦合性低 它定義了一種一對多的關係,可使多個觀察者對象對一個主題對象進行監聽,當這個主題對象發生改變時,依賴的全部對象都會被通知到。
二者的區別: 1.觀察者模式中,觀察者知道Subject ,二者是相關聯的,而發發布訂閱者只有經過信息代理進行通訊 2.在發佈訂閱模式中,組件式鬆散耦合的。正好和觀察者模式相反。 3.觀察者大部分是同步的,好比事件的觸發。Subject就會調用觀察者的方法。而發佈訂閱者大多數是異步的() 4.觀察者模式須要在單個應用程序地址空間中實現,而發佈訂閱者更像交叉應用模式。
1004001111 數據結構和算法
1、兩個棧實現一個隊列,兩個隊列實現一個棧 www.cnblogs.com/MrListening…
2、紅黑樹(解決二叉樹依次插入多個節點時的線型排列) juejin.im/post/5a27c6…
3、最小棧的實現(查找最小元素,用兩個棧配合棧內元素的下標)juejin.im/post/5a2ff8…
4、十大排序 1.冒泡排序:重複走訪過要排序的數列,一次比較兩個元素,若是他們的順序錯誤就把它們交換過來。 實現過程:1.比較相鄰的元素。若是第一個比第二個大,就交換他們兩個 2.對每一對相鄰元素做一樣的工做,從開始第一對到結尾的最後一對,這樣在最後的元素應該會是最大的數 3.針對全部的元素重複以上的步驟,除了最後一個 4.重複步驟1-3,直到排序完成。 2.選擇排序:首先在未排序序列中找到最小值,放在排序序列的起始位置,而後,在從剩下未排序元素中繼續尋找最小值,而後放在與排序序列的末尾 實現過程:
3.插入排序:構建有序序列,對於未排序數據,在已排序序列中衝後向前掃描,找到相應位置並插入
實現過程:1.從第一個元素開始,該元素能夠認爲已經被排序
2.取出下一個元素,在已排序的元素序列中衝後向前掃描
3.若是該元素(以排序)大於新元素,將元素向後移一位
4.在取出一個元素,比較以前的,直到找到本身合適的位置
4.桶排序:將數據分佈到有限數量的桶裏,每一個桶在分別排序
1.快速排序:快速排序使用分治法把一個串(list)分爲兩個子串(sub-lists).具體算法實現
實現過程:1.從數組中挑出一個元素,成爲一個基準
2.從新排列數組,全部元素比基準小的擺在基準前面,全部元素比基準大的擺在基準後面(相同的能夠擺在一邊)
這個分區退出以後,該基準就處於數列的中間位置。成爲分區操做。
3.遞歸的把小於基準值的子數列和大於基準值元素的子數列排序
算法實現: function quickSort (arr) {
if (arr.length <= 1) {return arr}
var destIndex = Math.floor(arr.length/2)
var left = [], right = [];
var dest = arr.splice(destIndex,1)[0];
for (var i =0;i<arr.length;i++){
if (arr[i]<dest) {
left.push(arr[i])
} else {
right.push(arr[i]) }
return quickSort(left).concat([dest],quickSort(right)
2.堆排序:利用對這種數據結構所涉及的一種排序算法,堆積是一個近乎徹底二叉樹的結構,並同時知足堆積的性質:即子節點的鍵值或索引老是小於(或大於)它的父節點。
實現過程:1.
複製代碼
5、數組去重 juejin.im/post/5aed61… 1.雙重循環 2.indexOf 3.數組排序去重 最快你Olong
6、字符串 判斷迴文字符串:(遞歸的思想) 1.字符串分隔,倒轉,聚合[...obj].reverse().join('') 2.字符串頭部和尾部,逐次向中間檢測 實現:function isPalindrome(line) { line += ''; for (var i=0,j=line.length-1;i<j;i++,j--) { if (line.chartAt(i) !== line.chartAt(j) { return false }
3.遞歸
複製代碼
7、二分查找(有序數組的查找) 二分查找能夠解決已排序數組的查找問題,即只要數組中包含T(要查找的值),那麼經過不斷的縮小包含T的數據範圍,就能夠最終要找到的數 (1) 一開始,數據範圍覆蓋整個數組。 (2) 將數組的中間項與T進行比較,若是T比數組的中間項小,則到數組的前半部分繼續查找,反之,則到數組的後半部分繼續查找。 (3) 就這樣,每次查找均可以排除一半元素,至關於範圍縮小一半。這樣反覆比較,反覆縮小範圍,最終會在數組中找到T 代碼實現:function binarySearch (data, dest, start, end){ var end = end || data.length-1; var start = start || 0; var m = Math.floor((start+end)/2); if (dest<data[m]){ return binarySearch(data, dest, 0, m-1) } else { return binarySearch(data, dest, m+1, end) }} return false
手寫代碼
複製代碼
1、動手實現一個bind(原理經過apply,call) 一句話歸納:1.bind()返回一個新函數,並不會當即執行。 2.bind的第一個參數將做爲他運行時的this,以後的一系列參數將會在傳遞的實參前傳入做爲他的參數 3.bind返回函數做爲構造函數,就是能夠new的,bind時指定的this值就會消失,但傳入的參數依然生效 Function.prototype.bind = function (obj, arg) { var arg = Array.prototype.slice.call(arguments, 1); var context = this; var bound = function (newArg) { arg = arg.concat(Array.prototype.slice.call(newArg); return context.apply(obj, arg) } var F = function () {} // 在new一個bind會生成新函數,必須的條件就是要繼承原函數的原型,所以用到寄生繼承來完成咱們的過程 F.prototype = context.prototype; bound.prototype = new F(); return bound; }
2、 AJAX (異步的javascript和xml) ajax的原理:至關於在用戶和服務器之間加一箇中間層(ajax引擎),使用戶操做與服務器響應異步化。 優勢:在不刷新整個頁面的前提下與服務器通訊維護數據。不會致使頁面的重載 能夠把前端服務器的任務轉嫁到客服端來處理,減輕服務器負擔,節省寬帶 劣勢:不支持back。對搜索引擎的支持比較弱;不容易調試 怎麼解決呢?經過location.hash值來解決Ajax過程當中致使的瀏覽器前進後退按鍵失效, 解決之前被人常遇到的重複加載的問題。主要比較先後的hash值,看其是否相等,在判斷是否觸發ajax function getData(url) { var xhr = new XMLHttpRequest(); // 建立一個對象,建立一個異步調用的對象 xhr.open('get', url, true) // 設置一個http請求,設置請求的方式,url以及驗證身份 xhr.send() //發送一個http請求 xhr.onreadystatechange = function () { //設置一個http請求狀態的函數 if (xhr.readyState == 4 && xhr.status ==200) { console.log(xhr.responseText) // 獲取異步調用返回的數據 } } } Promise(getData(url)).resolve(data => data)
AJAX狀態碼:0 - (未初始化)尚未調用send()方法
1 - (載入)已調用send方法,正在發送請求
2 - (載入完成呢)send()方法執行完成
3 - (交互)正在解析相應內容
4 - (完成)響應內容解析完成,能夠在客戶端調用了
複製代碼
3、函數節流(throttle) function throttle (func, wait) { var timeout; var previous = 0; return function () { context = this; args = arguments; if (!timeout) { timeout = setTimeout(() => { timeout = null; func.apply(context,args) }, wait); } } }
}
4、函數防抖(dobounce) function debounce (func, wait) { var timeout; return function() { var context = this; var args = arguments; clearTimeout(timeout); timeout = setTimeout(() => { func.apply(context,args) }, wait); } }
5、實現一個函數clone,能夠對JavaScript中的5種主要的數據類型(包括Number、String、Object、Array、Boolean)進行值複製
Object.prototype.clone = function() {
var newObject = this.constructor === Array ? [] : {} //對象的深拷貝 獲取對應的構造函數 [] 或者 {}
for (let e in this) { //遍歷對象的屬性 in this[e]
newObject[e] = typeof this[e] === 'object' ? this[e].clone() : this[e] //對象中的屬性若是仍是對象 那就繼續遞歸 不然就返回基本的數據類型
}
return newObject
}
複製代碼
6、實現一個簡單的Promise juejin.im/post/5b2f02… class Promise { constructor (executor) { // executor裏面有兩個參數,一個叫resolve(成功),一個叫reject(失敗)。 this.status = 'pending', this.value = undefined; this.reason = undefined; // 成功存放的數組 this.onResolvedCallbacks = []; // 失敗存放法數組 this.onRejectedCallbacks = []; let resolve = (value) => { if (this.status == 'pending') { this.status = 'resolve'; this.value = value; this.onResolvedCallbacks.forEach(fn => fn()) } }
let reject = (reason) => {
if (this.status == 'pending') {
this.status = 'reject';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn())
}
}
try{
executor(resolve, reject);
} catch (err) {
reject(err);
}
複製代碼
} then (onFullFilled,onRejected) { if (this.status == 'resolved') { onFullFilled(this.value) } if (this.status == 'rejectd') { onRejected(this.reason); } if (this.status == 'pending') { this.onResolvedCallbacks.push(()=>{ onFullFilled(this.value); }) this.onRejectedCallbacks.push(()=> { onRejected(this.reason); }) }
} }
const p = new Promise((resolve, reject) => { setTimeout(() => { resolve('hello world') }, 1000); }) p.then((data) =>{ console.log(data) },(err) =>{ console.log(err); })
7、發佈訂閱者模式(觀察者模式)
var event = {}; // 發佈者 event.clientList = [] //發佈者的緩存列表
event.listen = function (fn) { // 增長訂閱者函數 this.clientList.push(fn) }
event.trigger = function () { // 發佈信息 for (var i =0;i<this.clientList.length;i++) { var fn = this.clientList[i]; fn.apply(this, arguments); } }
event.listen (function(time) { console.log('正式上班時間爲:' +time) }) event.trigger ('2018/7')
8、手動寫一個node服務器 const http = require('http'); const fs = require('fs'); const server = http.createServer((req,res) => { if (reu.url == '/') { const indexFile = fs.createReadStream('./index.html') req.writeHead(200,{'context-Type':'text/html;charset = utf8}) indexFile.pipe(res) } server.listen(8080)