征服前端面試(上篇)

JavaScript

原型

咱們建立的每個函數,均可以有一個prototype屬性,該屬性指向一個對象。這個對象,就是原型。javascript

當咱們在建立對象時,能夠根據本身的需求,選擇性的將一些屬性和方法經過prototype屬性,掛載在原型對象上。而每個new出來的實例,都有一個proto屬性,該屬性指向構造函數的原型對象,經過這個屬性,讓實例對象也可以訪問原型對象上的方法。所以,當全部的實例都可以經過proto訪問到原型對象時,原型對象的方法與屬性就變成了共有方法與屬性。java

經過圖示咱們能夠看出,構造函數的prototype與全部實例對象的proto都指向原型對象。而原型對象的constructor指向構造函數。es6

原型鏈

咱們知道全部的函數都有一個叫作toString的方法。那麼這個方法究竟是在哪裏的呢?json

先隨意聲明一個函數:跨域


其中foo是Function對象的實例。而Function的原型對象同時又是Object的實例。這樣就構成了一條原型鏈。原型鏈的訪問,其實跟做用域鏈有很大的類似之處,他們都是一次單向的查找過程。所以實例對象可以經過原型鏈,訪問處處於原型鏈上對象的全部屬性與方法。這也是foo最終可以訪問處處於Object原型對象上的toString方法的緣由。數組

做用域鏈

做用域鏈的做用是保證執行環境裏有權訪問的變量和函數是有序的,做用域鏈的變量只能向上訪問,變量訪問到window對象即被終止,做用域鏈向下訪問變量是不被容許的。瀏覽器

閉包

  • 第一種理解(紅寶書):是指有權訪問另外一個函數做用域中的變量的函數,建立閉包的最多見的方式就是在一個函數內建立另外一個函數,經過另外一個函數訪問這個函數的局部變量緩存

  • 第二種理解(你不知道的javascript):當函數能夠記住並訪問所在的詞法做用域時,就產生了閉包,這個函數持有對該詞法做用域的引用,這個引用就叫作閉包安全

  • 閉包本質仍是函數,只不過這個函數綁定了上下文環境(函數內部引用的全部變量)性能優化

缺點:常駐內存,會增大內存使用量,使用不當很容易形成內存泄露。
做用(使用場景):能夠用來管理私有變量和私有方法,將對變量(狀態)的變化封裝在安全的環境中,使得這些變量不能被外部隨意修改,同時又能夠經過指定的函數接口來操做。
閉包有三個特性:
1.函數嵌套函數
2.函數內部能夠引用外部的參數和變量
3.參數和變量不會被垃圾回收機制回收

題外話:

  • JavaScript的做用域就是詞法做用域而不是動態做用域,

  • 詞法做用域最重要的特徵是它的定義過程發生在代碼的書寫階段

  • 動態做用域的做用域鏈是基於調用棧的 詞法做用域的做用域鏈是基於代碼中的做用域嵌套

this

JavaScript的this老是指向一個對象,而具體指向哪一個對象是在運行時基於函數的執行環境動態綁定的,而非函數被聲明時的環境。

this的指向:

一、做爲普通函數調用(this指向全局對象window對象)
二、做爲對象的方法調用(this指向該對象)
三、構造器調用(this指向用new返回的這個對象)
四、call、apply、bind的調用(this指向第一個參數對象)

高階函數

一、函數做爲參數傳遞
二、函數做爲返回值輸出

new操做符具體幹了什麼呢?

一、建立一個新對象
二、將構造函數的做用域賦給新對象(所以this就指向了這個新對象)
三、執行構造函數中的代碼(爲這個新對象添加屬性)
四、返回新對象

繼承

一、簡單原型鏈繼承

缺點:修改sub1.name後sub2.name也變了,由於來自原型對象的引用屬性是全部實例共享的。

二、構造函數式繼承

 

缺點:沒法實現函數複用,每一個子類實例都持有一個新的fun函數,太多了就會影響性能,內存爆炸。。

三、組合式繼承

 

缺點:子類原型上有一份多餘的父類實例屬性,由於父類構造函數被調用了兩次,生成了兩份,而子類實例上的那一份屏蔽了子類原型上父類的。。。又是內存浪費。

四、寄生組合式繼承

 

五、es6的class繼承方式

es6引入了class、extends、super、static(部分爲ES2016標準)

null和undefined的區別?

一、null是一個表示」無」的對象,轉爲數值時爲0;undefined是一個表示」無」的原始值,轉爲數值時爲NaN。
二、undefined表示」缺乏值」,就是此處應該有一個值,可是尚未定義。
三、null表示」沒有對象」,即該處不該該有值。

call、apply、bind的區別

  • 三者都是用來改變函數的this對象的指向的。

  • 三者第一個參數都是this要指向的對象,也就是想指定的上下文。

  • call 傳入的參數數量不固定,第二部分參數要一個一個傳,用,隔開。

  • apply 接受兩個參數,第二個參數爲一個帶下標的集合,能夠爲數組,也能夠爲類數組。

  • bind 是返回一個改變了上下文的函數副本,便於稍後調用;apply 、call 則是當即調用 。

本地存儲

  • sessionStorage用於本地存儲一個會話(session)中的數據,這些數據只有在同一個會話中的頁面才能訪問而且當會話結束後數據也隨之銷燬。所以sessionStorage不是一種持久化的本地存儲,僅僅是會話級別的存儲。

  • localStorage用於持久化的本地存儲,除非主動刪除數據,不然數據是永遠不會過時的。

cookie 和session

一、cookie數據存放在客戶的瀏覽器上,session數據放在服務器上。
二、cookie不是很安全,別人能夠分析存放在本地的COOKIE並進行COOKIE欺騙,考慮到安全應當使用session。
三、session會在必定時間內保存在服務器上。當訪問增多,會比較佔用你服務器的性能,考慮到減輕服務器性能方面,應當使用COOKIE。
四、單個cookie保存的數據不能超過4K,不少瀏覽器都限制一個站點最多保存20個cookie。每次請求一個新的頁面的時候Cookie都會被髮送過去,與服務器進行交互。

XML和JSON的區別?

一、數據體積方面。
JSON相對於XML來說,數據的體積小,傳遞的速度更快些。
二、數據交互方面。
JSON與JavaScript的交互更加方便,更容易解析處理,更好的數據交互。
三、數據描述方面。
JSON對數據的描述性比XML較差。
四、傳輸速度方面。
JSON的速度要遠遠快於XML。

如何實現瀏覽器內多個標籤頁之間的通訊?

調用localstorge、cookies等本地存儲方式

線程與進程的區別

一、一個程序至少有一個進程,一個進程至少有一個線程.
二、線程的劃分尺度小於進程,使得多線程程序的併發性高。
三、進程在執行過程當中擁有獨立的內存單元,而多個線程共享內存,從而極大地提升了程序的運行效率。
四、線程在執行過程當中與進程仍是有區別的。每一個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。可是線程不可以獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。
五、從邏輯角度來看,多線程的意義在於一個應用程序中,有多個執行部分能夠同時執行。但操做系統並無將多個線程看作多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。

漸進加強和優雅降級

  • 漸進加強 :針對低版本瀏覽器進行構建頁面,保證最基本的功能,而後再針對高級瀏覽器進行效果、交互等改進和追加功能達到更好的用戶體驗。

  • 優雅降級 :一開始就構建完整的功能,而後再針對低版本瀏覽器進行兼容。

性能優化

  • 網頁內容

    • 減小 http請求次數

    • 減小 DNS查詢次數

    • 避免頁面跳轉

    • 緩存 Ajax

    • 延遲加載

    • 提早加載

    • 減小 DOM元素數量

    • 避免 404

  • 服務器

    • 使用CDN(內容分發網絡)

    • 添加Expires或Cache-Control報文頭

    • Gzip壓縮傳輸文件

  • CSS

    • 將樣式表置頂

    • 用代替@import

  • JavaScript

    • 把腳本置於頁面底部

    • 使用外部JavaScript和CSS

    • 精簡JavaScript和CSS

    • 去除重複腳本

    • 減小DOM訪問

  • 圖片

    • 優化圖像

    • 優化CSS Spirite

    • 不要在HTML中縮放圖片

    • favicon.ico要小並且可緩存

如何解決跨域問題?

jsonp、CORS、document.domain+iframe、window.name、window.postMessage

jsonp的原理是動態插入script標籤

請解釋一下 JavaScript 的同源策略。

這裏的同源策略指的是:協議,域名,端口相同,同源策略是一種安全協議。

指一段腳本只能讀取來自同一來源的窗口和文檔的屬性。

哪些操做會形成內存泄漏?

一、內存泄漏指任何對象在您再也不擁有或須要它以後仍然存在。
二、垃圾回收器按期掃描對象,並計算引用了每一個對象的其餘對象的數量。若是一個對象的引用數量爲 0(沒有其餘對象引用過該對象),或對該對象的唯一引用是循環的,那麼該對象的內存便可回收。
三、setTimeout 的第一個參數使用字符串而非函數的話,會引起內存泄漏。
閉包、控制檯日誌、循環(在兩個對象彼此引用且彼此保留時,就會產生一個循環)

Javascript垃圾回收方法

一、標記清除:這是JavaScript最多見的垃圾回收方式,當變量進入執行環境的時候,好比函數中聲明一個變量,垃圾回收器將其標記爲「進入環境」,當變量離開環境的時候(函數執行結束)將其標記爲「離開環境」。

二、引用計數:引用計數的策略是跟蹤記錄每一個值被使用的次數,當聲明瞭一個 變量並將一個引用類型賦值給該變量的時候這個值的引用次數就加1,若是該變量的值變成了另一個,則這個值得引用次數減1,當這個值的引用次數變爲0的時 候,說明沒有變量在使用,這個值無法被訪問了,所以能夠將其佔用的空間回收,這樣垃圾回收器會在運行的時候清理掉引用次數爲0的值佔用的空間。

事件、IE與火狐的事件機制有什麼區別? 如何阻止冒泡?

事件處理機制:IE是事件冒泡、firefox同時支持兩種事件模型,也就是:捕獲型事件和冒泡型事件。

阻止冒泡:ev.stopPropagation()

說說嚴格模式的限制

  • 變量必須聲明後再使用

  • 函數的參數不能有同名屬性,不然報錯

  • 禁止this指向全局對象

  • 不能使用with語句

  • 增長了保留字

  • arguments不會自動反映函數參數的變化

設立」嚴格模式」的目的:

消除Javascript語法的一些不合理、不嚴謹之處,減小一些怪異行爲;

消除代碼運行的一些不安全之處,保證代碼運行的安全;

提升編譯器效率,增長運行速度;

爲將來新版本的Javascript作好鋪墊。

請解釋什麼是事件代理

事件代理(Event Delegation),又稱之爲事件委託。便是把本來須要綁定的事件委託給父元素,讓父元素擔當事件監聽的職務。事件代理的原理是DOM元素的事件冒泡。使用事件代理的好處是能夠提升性能。

Event Loop、消息隊列、事件輪詢

異步函數在執行結束後,會在事件隊列中添加一個事件(回調函數)(遵循先進先出原則),主線程中的代碼執行完畢後(即一次循環結束),下一次循環開始就在事件隊列中「讀取」事件,而後調用它所對應的回調函數。這個過程是循環不斷的,因此整個的這種運行機制又稱爲Event Loop(事件循環)

主線程運行的時候,產生堆(heap)和棧(stack),棧中的代碼(同步任務)調用各類外部API,它們在」任務隊列」中加入各類事件(click,load,done)。只要棧中的代碼執行完畢,主線程就會去讀取」任務隊列」,依次執行那些事件所對應的回調函數。

執行棧中的代碼(同步任務),老是在讀取」任務隊列」(異步任務)以前執行。

緩存

瀏覽器緩存(Browser Caching)是瀏覽器端保存數據用於快速讀取或避免重複資源請求的優化機制,有效的緩存使用能夠避免重複的網絡請求和瀏覽器快速地讀取本地數據,

http緩存

http緩存是基於HTTP協議的瀏覽器文件級緩存機制。即針對文件的重複請求狀況下,瀏覽器能夠根據協議頭判斷從服務器端請求文件仍是從本地讀取文件
判斷expires,若是未過時,直接讀取http緩存文件

indexDB

是一個在客戶端存儲可觀數量的結構化數據,而且爲這些數據添加索引進行高性能檢索。

cookie

指通常網站爲了辨別用戶身份、儲存在用戶本地終端上的數據(一般通過加密)。cookie通常經過http請求中在頭部一塊兒發送到服務器端。一條cookie記錄主要由鍵、值、域、過時時間、大小組成,通常用戶保存用戶的認證信息。

localstorage

localStorage是h5的一種新的本地緩存方案,加快下次頁面打開時的渲染速度,除非主動刪除數據,不然數據是永遠不會過時的。

sessionstorage

也是h5的一種本地緩存方案,數據的存儲僅特定於某個會話中,也就是說數據只保持到瀏覽器關閉,當瀏覽器關閉後從新打開這個頁面時, 以前的存儲已經被清除。

相關文章
相關標籤/搜索