程式設計師面試30題,你面試失敗的原因都在這裡!
時間飛逝,轉眼間從離開百度到創辦愛創課堂前端培訓學校近3年了。工作也發生了巨大變化,從以前的企業專案開發到現在在學校日復一日地為學生授課,但無論對著計算機程式設計,還是為學生講述前端知識,都十分讓我享受。
每到畢業季,看著自己帶出的學生找到理想的工作,心中亦是十分欣慰。學生求職中,經常會問我一些面試中的問題,每次耐心地幫他們解答,對他們幫助很大。
臨近畢業的學生很多恐懼面試,所以在學校內部我整理了一些面試題冊子與學生分享,學生受益頗多。再後來,為使在這裡畢業的更多學生持續地學習更廣闊的知識,愛創課堂組織了一個“愛創課堂每日一題”活動,每天推出一道與工作相關的技術問題,受到廣大畢業學生好評……
通過這些活動我認識到,不論是在面試中,還是工作中,通過學習瞭解確實可以避免少踩一些坑,少走一些彎路,於是我將培訓學校內部用的前端面試知識,整理成一本書。
希望能夠與更多的讀者分享愛創課堂的知識;希望《前端程式設計師面試祕籍》能夠幫助那些正在找工作的人順利找到工作;也希望這本書能夠幫助那些在工作中遇到問題而躊躇不前的人順利解決問題;同時也希望這本書能夠幫助那些學習前端、期望瞭解前端更多知識的人。
1.JavaScript有哪些垃圾回收機制?
答:有以下垃圾回收機制。
標記清除(mark and sweep)
這是JavaScript最常見的垃圾回收方式。當變數進入執行環境的時候,比如在函式中宣告一個變數,垃圾回收器將其標記為“進入環境”。當變數離開環境的時候(函式執行結束),將其標記為“離開環境”。
垃圾回收器會在執行的時候給儲存在記憶體中的所有變數加上標記,然後去掉環境中的變數,以及被環境中變數所引用的變數(閉包)的標記。在完成這些之後仍然存在的標記就是要刪除的變數。
引用計數(reference counting)
在低版本的IE中經常會發生記憶體洩漏,很多時候就是因為它採用引用計數的方式進行垃圾回收。
引用計數的策略是跟蹤記錄每個值被使用的次數。當聲明瞭一個變數並將一個引用型別賦值給該變數的時候,這個值的引用次數就加1。如果該變數的值變成了另外一個,則這個值的引用次數減1。當這個值的引用次數變為0的時候,說明沒有變數在使用,這個值沒法被訪問。
因此,可以將它佔用的空間回收,這樣垃圾回收器會在執行的時候清理引用次數為0的值佔用的空間。
在IE中雖然JavaScript物件通過標記清除的方式進行垃圾回收,但是BOM與DOM物件是用引用計數的方式回收垃圾的。也就是說,只要涉及BOM和DOM,就會出現迴圈引用問題。
2.列舉幾種型別的DOM節點
答:有以下幾類DOM節點。
整個文件是一個文件節點。
每個HTML標籤是一個元素節點。
每一個HTML屬性是一個屬性節點。
包含在HTML元素中的文字是文字節點。
3.談談script標籤中defer和async屬性的區別。
答:區別如下。
(1)defer屬性規定是否延遲執行指令碼,直到頁面載入為止。async屬性規定指令碼一旦可用,就非同步執行。
(2)defer並行載入JavaScript檔案,會按照頁面上script標籤的順序執行。async並行載入JavaScript檔案,下載完成立即執行,不會按照頁面上script標籤的順序執行。
4.說說你對閉包的理解。
答:使用閉包主要是為了設計私有的方法和變數。閉包的優點是可以避免全域性變數的汙染;缺點是閉包會常駐記憶體,增加記憶體使用量,使用不當很容易造成記憶體洩漏。在JavaScript中,函式即閉包,只有函式才會產生作用域。
閉包有3個特性。
(1)函式巢狀函式。
(2)在函式內部可以引用外部的引數和變數。
(3)引數和變數不會以垃圾回收機制回收。
5.解釋一下unshift()方法。
答:該方法在陣列啟動時起作用,與push()不同。它將引數成員新增到陣列的答頂部。下面給出一段示例程式碼。
var name=["john"]
name.unshift("charlie");
name.unshift("joseph","Jane");
console.log(name);
輸出如下所示。
[" joseph "," Jane ", " charlie ", " john "]
6.encodeURI()和decodeURI()的作用是什麼?
答:encodeURl()用於將URL轉換為十六進位制編碼。而decodeURI()用於將編碼的URL轉換回正常URL。
7.為什麼不建議在JavaScript中使用innerHTML?
答:通過innerHTML修改內容,每次都會重新整理,因此很慢。在innerHTML中沒有驗證的機會,因此更容易在文件中插入錯誤程式碼,使網頁不穩定。
8.如何在不支援JavaScript的舊瀏覽器中隱藏JavaScript程式碼?
答:在<script>標籤之後的程式碼中新增“<!--”,不帶引號。
在</script>標籤之前新增“// -->”,程式碼中沒有引號。
舊瀏覽器現在將JavaScript程式碼視為一個長的HTML註釋,而支援JavaScript的瀏覽器則將“<!--”和“// -->”作為一行註釋。
9.在DOM操作中怎樣建立、新增、移除、替換、插入和查詢節點?
答:具體方法如下。
(1)通過以下程式碼建立新節點。
createDocumentFragment() //建立一個DOM片段
createElement() //建立一個具體的元素
createTextNode() //建立一個文字節點
(2)通過以下程式碼新增、移除、替換、插入節點。
appendChild()
removeChild()
replaceChild()
insertBefore() //並沒有insertAfter()
(3)通過以下程式碼查詢節點。
getElementsByTagName() //通過標籤名稱查詢節點
getElementsByName() //通過元素的name屬性的值查詢節點(IE容錯能力較強,會得到一個數
//組,其中包括id等於name值的節點)
getElementById() //通過元素Id查詢節點,具有唯一性
10.如何實現瀏覽器內多個標籤頁之間的通訊?
答:呼叫localstorge、cookie等資料儲存通訊方式。
11.null和undefined的區別是什麼?
答:null是一個表示“無”的物件,轉為數值時為0;undefined是一個表示“無”的原始值,轉為數值時為NaN。
當宣告的變數還未初始化時,變數的預設值為undefined。
null用來表示尚未存在的物件,常用來表示函式企圖返回一個不存在的物件。
undefined表示“缺少值”,即此處應該有一個值,但是還沒有定義,典型用法是如下。
(1)如果變數聲明瞭,但沒有賦值,它就等於undefined。
(2)當呼叫函式時,如果沒有提供應該提供的引數,該引數就等於undefined。
(3)如果物件沒有賦值,該屬性的值為undefined。
(4)當函式沒有返回值時,預設返回undefined。
null表示“沒有物件”,即此處不應該有值,典型用法是如下。
(1)作為函式的引數,表示該函式的引數不是物件。
(2)作為物件原型鏈的終點。
12.new操作符的作用是什麼?
答:作用如下。
(1)建立一個空物件。
(2)由this變數引用該物件。
(3)該物件繼承該函式的原型(更改原型鏈的指向)。
(4)把屬性和方法加入到this引用的物件中。
(5)新建立的物件由this引用,最後隱式地返回this,過程如下。
var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
13.JavaScript延遲載入的方式有哪些?
答:包括defer和async、動態建立DOM(建立script,插入DOM中,載入完畢後回撥、按需非同步載入JavaScript。
14.call()和apply() 的區別和作用是什麼?
答:作用都是在函式執行的時候,動態改變函式的執行環境(執行上下文)。
call和apply的第一個引數都是改變執行環境的物件。
區別如下。
call從第二個引數開始,每一個引數會依次傳遞給呼叫函式;apply的第二個引數是陣列,陣列的每一個成員會依次傳遞給呼叫函式。
如:
func.call(func1, var1, var2, var3)
對應的apply寫法為:
func.apply(func1, [var1, var2, var3])
15.哪些操作會造成記憶體洩漏?
答:記憶體洩漏指不再擁有或需要任何物件(資料)之後,它們仍然存在於記憶體中。
提示:垃圾回收器定期掃描物件,並計算引用了每個物件的其他物件的數量。如果一個物件的引用數量為0(沒有其他物件引用過該物件),或對該物件的唯一引用是迴圈的,那麼該物件佔用的記憶體立即被回收。
如果setTimeout 的第一個引數使用字串而非函式,會引發記憶體洩漏。
閉包、控制檯日誌、迴圈(在兩個物件彼此引用且彼此保留時,就會產生一個迴圈)等會造記憶體洩漏。
16.列舉IE與finefox的不同之處。
答:不同之處如下。
(1)IE支援currentStyle;Firefox使用getComputStyle。
(2)IE使用innerText;Firefox使用textContent。
(3)在透明度濾鏡方面,IE使用filter:alpha(opacity= num);Firefox使用-moz-opacity: num。
(4)在事件方面,IE使用attachEvent:Firefox使用addEventListener。
(5)對於滑鼠位置:IE使用event.clientX;Firefox使用event.pageX。
(6)IE使用event.srcElement;Firefox使用event.target。
(7)要消除list的原點,IE中僅須使margin:0即可達到最終效果;Firetox中需要設定margin:0、padding:0和list-style:none。
(8)CSS圓角:IE7以下不支援圓角。
17.講解一下JavaScript物件的幾種建立方式。
答:有以下建立方式。
(1)Object建構函式式。
(2)物件字面量式。
(3)工廠模式。
(4)安全工廠模式。
(5)建構函式模式。
(6)原型模式。
(7)混合建構函式和原型模式。
(8)動態原型模式。
(9)寄生建構函式模式。
(10)穩妥建構函式模式。
18.如何實現非同步程式設計?
答:具體方法如下。
方法 1,通過回撥函式。優點是簡單、容易理解和部署;缺點是不利於程式碼的閱讀和維護,各個部分之間高度耦合(Coupling),流程混亂,而且每個任務只能指定一個回撥函式。
方法 2,通過事件監聽。可以繫結多個事件,每個事件可以指定多個回撥函式,而且可以“去耦合”(Decoupling),有利於實現模組化;缺點是整個程式都要變成事件驅動型,執行流程會變得很不清晰。
方法 3,採用釋出/訂閱方式。性質與“事件監聽”類似,但是明顯優於後者。
方法 4,通過Promise物件實現。Promise物件是CommonJS工作組提出的一種規範,旨在為非同步程式設計提供統一介面。它的思想是,每一個非同步任務返回一個Promise物件,該物件有一個then方法,允許指定回撥函式。
19.請解釋一下JavaScript的同源策略。
答:同源策略是客戶端指令碼(尤其是JavaScript)的重要安全度量標準。它最早出自Netscape Navigator 2.0,目的是防止某個文件或指令碼從多個不同源裝載。
這裡的同源策略指的是協議、域名、埠相同。同源策略是一種安全協議。指一段指令碼只能讀取來自同一來源的視窗和文件的屬性。
20.為什麼要有同源限制?
答:我們舉例說明。比如一個黑客,他利用Iframe把真正的銀行登入頁面嵌到他的頁面上,當你使用真實的使用者名稱、密碼登入時,他的頁面就可以通過JavaScript讀取到你表單上input中的內容,這樣黑客就會輕鬆得到你的使用者名稱和密碼。
21.在JavaScript中,為什麼說函式是第一類物件?
答:第一類函式即JavaScript中的函式。這通常意味著這些函式可以作為引數傳遞給其他函式,作為其他函式的值返回,分配給變數,也可以儲存在資料結構中。
22.什麼是事件? IE與Firefox的事件機制有什麼區別? 如何阻止冒泡?
答:事件是在網頁中的某個操作(有的操作對應多個事件)。例如,當單擊一個按鈕時,就會產生一個事件,它可以被JavaScript偵測到。
在事件處理機制上,IE支援事件冒泡;Firefox同時支援兩種事件模型,也就是捕獲型事件和冒泡型事件。
阻止方法是ev.stopPropagation()。注意舊版IE中的方法ev.cancelBubble = true。
23.函式宣告與函式表示式的區別?
答:在JavaScript中,在向執行環境中載入資料時,解析器對函式宣告和函式表示式並非是一視同仁的。解析器會首先讀取函式宣告,並使它在執行任何程式碼之前可用(可以訪問)。至於函式表示式,則必須等到解析器執行到它所在的程式碼行,才會真正解析和執行它。
24.如何刪除一個cookie?
答:為了刪除cookie,要修改expires,程式碼如下。
document.cookie = 'user=icketang;expires = ' + new Date(0)
25.編寫一個方法,求一個字串的長度(單位是位元組)。
答:假設一個英文字元佔用一位元組,一箇中文字元佔用兩位元組:
function GetBytes(str){
var len = str.length;
var bytes = len;
for(var i=0; i<len; i++){
if (str.charCodeAt(i) > 255) bytes++;
}
return bytes;
}
alert(GetBytes("hello 愛創課堂!"));
26.對於元素,attribute和property的區別是什麼?
答:attribute是DOM元素在文件中作為HTML標籤擁有的屬性;property就是DOM元素在JavaScript中作為物件擁有的屬性。
對於HTML的標準屬性來說,attribute和property是同步的,會自動更新,但是對於自定義的屬性來說,它們是不同步的。
27.解釋延遲指令碼在JavaScript中的作用。
答:預設情況下,在頁面載入期間,HTML程式碼的解析將暫停,直到指令碼停止執行。這意味著,如果伺服器速度較慢或者指令碼特別“沉重”,則會導致網頁延遲。在使用Deferred時,指令碼會延遲執行,直到HTML解析器執行。這縮短了網頁的載入時間,並且它們的顯示速度更快。
28.什麼是閉包(closure)?
答:為了說明閉包,建立一個閉包。
function hello() {
// 函式執行完畢,變數仍然存在
var num = 100;
var showResult= function() { alert(num); }
num++;
return showResult;
}
var showResult= hello();
showResult()//執行結果:彈出101
執行hello()後,hello()閉包內部的變數會存在,而閉包內部函式的內部變數不會存在,使得JavaScript的垃圾回收機制不會收回hello()佔用的資源,因為hello()中內部函式的執行需要依賴hello()中的變數。
29.如何判斷一個物件是否屬於某個類?
答:使用instanceof關鍵字,判斷一個物件是否是類的例項化物件;使用constructor屬性,判斷一個物件是否是類的建構函式。
30.JavaScript中如何使用事件處理程式?
答:事件是由使用者與頁面的互動(例如單擊連結或填寫表單)導致的操作。需要一個事件處理程式來保證所有事件的正確執行。事件處理程式是物件的額外屬性。此屬性包括事件的名稱和事件發生時採取的操作。
張容銘 著
本書針對前端知識所涉及的方方面面,總結歸納了30個模組,提出了1076道前端面試題,模擬了真實的面試場景。從面試官的角度出發,針對某一知識點,並以面試官的口吻提出疑問。在解答問題過程中,站在應試者的角度給出答案。讓讀者進入真實的企業面試氛圍。書中面試題極具針對性,並具有一定的獨立性,讀者可以根據個人喜好,可以針對性地閱覽某一章節。
邀請10名好友關注非同步圖書10天,即可免費獲得非同步新書。
長按二維碼,可以關注我們喲
每天與你分享IT好文。
點選閱讀原文,購買《前端程式設計師面試祕籍》
閱讀原文