史上最全面試題總結JavaScript
1.eval是做什麼的?
它的功能是把對應的字串解析成JS程式碼並執行; 應該避免使用eval,不安全,非常耗效能(2次,一次解析成js語句,一次執行)。
null,undefined 的區別?
目前,null和undefined基本是同義的,只有一些細微的差別。
null表示"沒有物件",即該處不應該有值。典型用法是:
(1) 作為函式的引數,表示該函式的引數不是物件。
(2) 作為物件原型鏈的終點。
Object.getPrototypeOf(Object.prototype)
// null
undefined表示"缺少值",就是此處應該有一個值,但是還沒有定義。典型用法是:
(1)變數被聲明瞭,但沒有賦值時,就等於undefined。
(2) 呼叫函式時,應該提供的引數沒有提供,該引數等於undefined。
(3)物件沒有賦值的屬性,該屬性的值為undefined。
(4)函式沒有返回值時,預設返回undefined。
var i;
i // undefined
function f(x){console.log(x)}
f() // undefined
var o = new Object();
o.p // undefined
var x = f();
x // undefined
寫一個通用的事件偵聽器函式
// event(事件)工具集,來源:github.com/markyun
markyun.Event = {
// 頁面載入完成後
readyEvent : function(fn) {
if (fn==null) {
fn=
}
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = fn;
} else {
window.onload = function() {
oldonload();
fn();
};
}
},
// 視能力分別使用dom0||dom2||IE方式 來繫結事件
// 引數: 操作的元素,事件名稱 ,事件處理程式
addEvent : function(element, type, handler) {
if (element.addEventListener) {
//事件型別、需要執行的函式、是否捕捉
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent('on' + type, function() {
handler.call(element);
});
} else {
element['on' + type] = handler;
}
},
// 移除事件
removeEvent : function(element, type, handler) {
if (element.removeEnentListener) {
element.removeEnentListener(type, handler, false);
} else if (element.datachEvent) {
element.detachEvent('on' + type, handler);
} else {
element['on' + type] = null;
}
},
// 阻止事件 (主要是事件冒泡,因為IE不支援事件捕獲)
stopPropagation : function(ev) {
if (ev.stopPropagation) {
ev.stopPropagation();
} else {
ev.cancelBubble = true;
}
},
// 取消事件的預設行為
preventDefault : function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
// 獲取事件目標
getTarget : function(event) {
return event.target || event.srcElement;
},
// 獲取event物件的引用,取到事件的所有資訊,確保隨時能使用event;
getEvent : function(e) {
var ev = e || window.event;
if (!ev) {
var c = this.getEvent.caller;
while (c) {
ev = c.arguments[0];
if (ev && Event == ev.constructor) {
break;
}
c = c.caller;
}
}
return ev;
}
};
你用閉包來做什麼?如果你有最喜歡的應用場景,舉一些例子。
DOM操作——怎樣新增、移除、移動、複製、建立和查詢節點。
(1)建立新節點
createDocumentFragment() //
建立一個
DOM
片段
createElement() //
建立一個具體的元素
createTextNode() //
建立一個文字節點
(2)新增、移除、替換、插入
appendChild()
removeChild()
replaceChild()
insertBefore() //
在已有的子節點前插入一個新的子節點
(3)查詢
getElementsByTagName() //
通過標籤名稱
getElementsByName() //
通過元素的
Name
屬性的值
(IE
容錯能力較強,會得到一個數組,其中包括
id
等於
name
值的
)
getElementById() //通過元素Id,唯一性
html5有哪些新特性、移除了那些元素?如何處理HTML5新標籤的瀏覽器相容問題?如何區分 HTML 和 HTML5?
* HTML5 現在已經不是SGML 的子集,主要是關於影象,位置,儲存,多工等功能的增加。
*
拖拽釋放(Drag and drop) API
語義化更好的內容標籤(header,nav,footer,aside,article,section)
音訊、視訊API(audio,video)
畫布
(Canvas) API
地理(Geolocation) API
本地離線儲存localStorage
長期儲存資料,瀏覽器關閉後資料不丟失;
sessionStorage 的資料在瀏覽器關閉後自動刪除
表單控制元件,calendar、date、time、email、url、search
新的技術webworker, websocket, Geolocation* 移除的元素
純表現的元素:basefont,big,center,font, s,strike,tt,u;
對可用性產生負面影響的元素:
frame
,
frameset
,
noframes
;
支援
HTML5
新標籤:
* IE8/IE7/IE6
支援通過
document.createElement
方法產生的標籤,
可以利用這一特性讓這些瀏覽器支援
HTML5
新標籤,
瀏覽器支援新標籤後,還需要新增標籤預設的樣式:
*
當然最好的方式是直接使用成熟的框架、使用最多的是
html5shim
框架
<!--[if lt IE 9]>
<script> src="http://html5shim.googlecode.com/svn/trunk/html5.js"</script>
<![endif]-->
如何區分:
DOCTYPE
宣告
\
新增的結構元素
\
功能元素
8.iframe的優缺點?
1.<iframe>
優點:
解決載入緩慢的第三方內容如圖示和廣告等的載入問題
Security sandbox
並行載入指令碼
2.<iframe>
的缺點:
*iframe
會阻塞主頁面的
Onload
事件;
*
即時內容為空,載入也需要時間
*
沒有語意
9.如何實現瀏覽器內多個標籤頁之間的通訊?
呼叫
localstorge
、
cookies
等本地儲存方式
10.webSocket如何相容低瀏覽器?
Adobe Flash Socket 、 ActiveX HTMLFile (IE) 、
基於 multipart 編碼傳送 XHR 、基於長輪詢的 XHR
11.執行緒與程序的區別
一個程式至少有一個程序,一個程序至少有一個執行緒.
執行緒的劃分尺度小於程序,使得多執行緒程式的併發性高。
另外,程序在執行過程中擁有獨立的記憶體單元,而多個執行緒共享記憶體,從而極大地提高了程式的執行效率。
執行緒在執行過程中與程序還是有區別的。每個獨立的執行緒有一個程式執行的入口、順序執行序列和程式的出口。但是執行緒不能夠獨立執行,必須依存在應用程式中,由應用程式提供多個執行緒執行控制。
從邏輯角度來看,多執行緒的意義在於一個應用程式中,有多個執行部分可以同時執行。但作業系統並沒有將多個執行緒看做多個獨立的應用,來實現程序的排程和管理以及資源分配。這就是程序和執行緒的重要區別。
12.你如何對網站的檔案和資源進行優化?
期待的解決方案包括: 檔案合併 檔案最小化/檔案壓縮 使用 CDN 託管 快取的使用(多個域名來提供快取) 其他
13.請說出三種減少頁面載入時間的方法。
1.優化圖片
2.影象格式的選擇(GIF:提供的顏色較少,可用在一些對顏色要求不高的地方)
3.優化CSS(壓縮合並css,如margin-top,margin-left...)
4.網址後加斜槓(如www.campr.com/目錄,會判斷這個“目錄是什麼檔案型別,或者是目錄。)
5.標明高度和寬度(如果瀏覽器沒有找到這兩個引數,它需要一邊下載圖片一邊計算大小,如果圖片很多,瀏覽器需要不斷地調整頁面。這不但影響速度,也影響瀏覽體驗。
當瀏覽器知道了高度和寬度引數後,即使圖片暫時無法顯示,頁面上也會騰出圖片的空位,然後繼續載入後面的內容。從而載入時間快了,瀏覽體驗也更好了。)
6.減少http請求(合併檔案,合併圖片)。
14.你都使用哪些工具來測試程式碼的效能?
Profiler, JSPerf
(
http://jsperf.com/nexttick-vs-setzerotimeout-vs-settimeout
)
, Dromaeo
15.什麼是 FOUC(無樣式內容閃爍)?你如何來避免 FOUC?
FOUC - Flash Of Unstyled Content
文件樣式閃爍
<style type="text/css" media="all">@import "../fouc.css";</style>
而引用
CSS
檔案的
@import
就是造成這個問題的罪魁禍首。
IE
會先載入整個
HTML
文件的
DOM
,然後再去匯入外部的
CSS
檔案,因此,在頁面
DOM
載入完成到
CSS
匯入完成中間會有一段時間頁面上的內容是沒有樣式的,這段時間的長短跟網速,電腦速度都有關係。
解決方法簡單的出奇,只要在
<head>
之間加入一個
<link>
或者
<script>
元素就可以了。
16.null和undefined的區別?
null
是一個表示”無”的物件,轉為數值時為0;undefined
是一個表示”無”的原始值,轉為數值時為NaN
。
當宣告的變數還未被初始化時,變數的預設值為undefined
。null
用來表示尚未存在的物件,常用來表示函式企圖返回一個不存在的物件。
undefined
表示”缺少值”,就是此處應該有一個值,但是還沒有定義。典型用法是:
(
1
)變數被聲明瞭,但沒有賦值時,就等於
undefined
。
(
2)
呼叫函式時,應該提供的引數沒有提供,該引數等於
undefined
。
(
3
)物件沒有賦值的屬性,該屬性的值為
undefined
。
(
4
)函式沒有返回值時,預設返回
undefined
。
null
表示”沒有物件”,即該處不應該有值。典型用法是:
(
1
)
作為函式的引數,表示該函式的引數不是物件。
(
2
)
作為物件原型鏈的終點。
17.new操作符具體幹了什麼呢?
1
、建立一個空物件,並且
this
變數引用該物件,同時還繼承了該函式的原型。
2
、屬性和方法被加入到
this
引用的物件中。
3
、新建立的物件由
this
所引用,並且最後隱式的返回
this
。
var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
18.JSON 的瞭解?
JSON(JavaScript Object Notation)
是一種輕量級的資料交換格式。
它是基於
JavaScript
的一個子集。資料格式簡單
,
易於讀寫
,
佔用頻寬小
{'age':'12', 'name':'back'}
19.js延遲載入的方式有哪些?
defer
和
async
、動態建立
DOM
方式(建立
script
,插入到
DOM
中,載入完畢後
callBack
)、按需非同步載入
js
20.如何解決跨域問題?
jsonp
、
document.domain+iframe
、
window.name
、
window.postMessage
、伺服器上設定代理頁面
jsonp
的原理是動態插入
script
標籤
21.documen.write和 innerHTML的區別
document.write
只能重繪整個頁面
innerHTML
可以重繪頁面的一部分
22. .call() 和 .apply() 的區別和作用?
作用:動態改變某個類的某個方法的執行環境。
23.哪些操作會造成記憶體洩漏?
記憶體洩漏指任何物件在您不再擁有或需要它之後仍然存在。
垃圾回收器定期掃描物件,並計算引用了每個物件的其他物件的數量。如果一個物件的引用數量為
0
(沒有其他物件引用過該物件),或對該物件的惟一引用是迴圈的,那麼該物件的記憶體即可回收。
setTimeout
的第一個引數使用字串而非函式的話,會引發記憶體洩漏。
閉包、控制檯日誌、迴圈(在兩個物件彼此引用且彼此保留時,就會產生一個迴圈)
24.JavaScript中的作用域與變數宣告提升?
25.如何判斷當前指令碼執行在瀏覽器還是node環境中?
通過判斷
Global
物件是否為
window
,如果不為
window
,當前指令碼沒有執行在瀏覽器中
26.其他問題?
99%的網站都需要被重構是那本書上寫的?
*
網站重構:應用
web
標準進行設計(第
2
版)
32.javascript物件的幾種建立方式
1
,工廠模式
2
,建構函式模式
3
,原型模式
4
,混合建構函式和原型模式
5
,動態原型模式
6
,寄生建構函式模式
7
,穩妥建構函式模式
33.javascript繼承的6種方法
1
,原型鏈繼承
2
,借用建構函式繼承
3
,組合繼承
(
原型
+
借用構造
)
4
,原型式繼承
5
,寄生式繼承
6
,寄生組合式繼承
34.ajax過程
(1)
建立
XMLHttpRequest
物件
,
也就是建立一個非同步呼叫物件
.
(2)
建立一個新的
HTTP
請求
,
並指定該
HTTP
請求的方法、
URL
及驗證資訊
.
(3)
設定響應
HTTP
請求狀態變化的函式
.
(4)
傳送
HTTP
請求
.
(5)
獲取非同步呼叫返回的資料
.
(6)
使用
JavaScript
和
DOM
實現區域性重新整理
.
35.非同步載入和延遲載入
1.
非同步載入的方案:
動態插入
script
標籤
2.
通過
ajax
去獲取
js
程式碼,然後通過
eval
執行
3.script
標籤上新增
defer
或者
async
屬性
4.
建立並插入
iframe
,讓它非同步執行
js
5.
延遲載入:有些
js
程式碼並不是頁面初始化的時候就立刻需要的,而稍後的某些情況才需要的。
38.javascript裡面的繼承怎麼實現,如何避免原型鏈上面的物件共享
用建構函式和原型鏈的混合模式去實現繼承,避免物件共享可以參考經典的
extend()
函式,很多前端框架都有封裝的,就是用一個空函式當做中間變數
39.grunt, YUI compressor 和 google clojure用來進行程式碼壓縮的用法。
YUI Compressor
是一個用來壓縮
JS
和
CSS
檔案的工具,採用
Java
開發。
使用方法:
//
壓縮
JS
java -jar yuicompressor-2.4.2.jar --type js --charset utf-8 -v src.js > packed.js
//
壓縮
CSS
java -jar yuicompressor-2.4.2.jar --type css --charset utf-8 -v src.css > packed.css
40.Flash、Ajax各自的優缺點,在使用中如何取捨?
1
、
Flash ajax
對比
Flash
適合處理多媒體、向量圖形、訪問機器;對
CSS
、處理文字上不足,不容易被搜尋。
Ajax
對
CSS
、文字支援很好,支援搜尋;多媒體、向量圖形、機器訪問不足。
共同點:與伺服器的無重新整理傳遞訊息、使用者離線和線上狀態、操作
DOM
41.請解釋一下 JavaScript 的同源策略。
概念:同源策略是客戶端指令碼(尤其是Javascript
)的重要的安全度量標準。它最早出自Netscape Navigator2.0
,其目的是防止某個文件或指令碼從多個不同源裝載。
這裡的同源策略指的是:協議,域名,埠相同,同源策略是一種安全協議。
指一段指令碼只能讀取來自同一來源的視窗和文件的屬性。
為什麼要有同源限制?
我們舉例說明:比如一個黑客程式,他利用Iframe
把真正的銀行登入頁面嵌到他的頁面上,當你使用真實的使用者名稱,密碼登入時,他的頁面就可以通過Javascript
讀取到你的表單中input
中的內容,這樣使用者名稱,密碼就輕鬆到手了。
42.什麼是 “use strict”; ? 使用它的好處和壞處分別是什麼?
ECMAscript 5
添加了第二種執行模式:”嚴格模式”(strict mode)。顧名思義,這種模式使得Javascript
在更嚴格的條件下執行。
設立”嚴格模式”的目的,主要有以下幾個:
-
消除
Javascript
語法的一些不合理、不嚴謹之處,減少一些怪異行為
;
-
消除程式碼執行的一些不安全之處,保證程式碼執行的安全;
-
提高編譯器效率,增加執行速度;
-
為未來新版本的
Javascript
做好鋪墊。
注:經過測試IE6,7,8,9
均不支援嚴格模式。
缺點:
現在網站的JS
都會進行壓縮,一些檔案用了嚴格模式,而另一些沒有。這時這些本來是嚴格模式的檔案,被 merge
後,這個串就到了檔案的中間,不僅沒有指示嚴格模式,反而在壓縮後浪費了位元組。
43.GET和POST的區別,何時使用POST?
GET
:一般用於資訊獲取,使用
URL
傳遞引數,對所傳送資訊的數量也有限制,一般在
2000
個字元
POST
:一般用於修改伺服器上的資源,對所傳送的資訊沒有限制。
GET
方式需要使用
Request.QueryString
來取得變數的值,而
POST
方式通過
Request.Form
來獲取變數的值,
也就是說
Get
是通過位址列來傳值,而
Post
是通過提交表單來傳值。
然而,在以下情況中,請使用
POST
請求:
無法使用快取檔案(更新伺服器上的檔案或資料庫)
向伺服器傳送大量資料(
POST
沒有資料量限制)
傳送包含未知字元的使用者輸入時,
POST
比
GET
更穩定也更可靠
44.哪些地方會出現css阻塞,哪些地方會出現js阻塞?
js的阻塞特性:所有瀏覽器在下載JS
的時候,會阻止一切其他活動,比如其他資源的下載,內容的呈現等等。直到JS
下載、解析、執行完畢後才開始繼續並行下載
其他資源並呈現內容。為了提高使用者體驗,新一代瀏覽器都支援並行下載JS
,但是JS
下載仍然會阻塞其它資源的下載(例如.圖片,css檔案等)。
由於瀏覽器為了防止出現JS
修改DOM
樹,需要重新構建DOM
樹的情況,所以就會阻塞其他的下載和呈現。
嵌入JS
會阻塞所有內容的呈現,而外部JS
只會阻塞其後內容的顯示,2種方式都會阻塞其後資源的下載。也就是說外部樣式不會阻塞外部指令碼的載入,但會阻塞外部指令碼的執行。
CSS
怎麼會阻塞載入了?CSS
本來是可以並行下載的,在什麼情況下會出現阻塞載入了(在測試觀察中,IE6
下CSS
都是阻塞載入)
當CSS
後面跟著嵌入的JS
的時候,該CSS
就會出現阻塞後面資源下載的情況。而當把嵌入JS
放到CSS
前面,就不會出現阻塞的情況了。
根本原因:因為瀏覽器會維持html
中css
和js
的順序,樣式表必須在嵌入的JS執行前先載入、解析完。而嵌入的JS
會阻塞後面的資源載入,所以就會出現上面CSS
阻塞下載的情況。
嵌入JS
應該放在什麼位置?
1
、放在底部,雖然放在底部照樣會阻塞所有呈現,但不會阻塞資源下載。
2
、如果嵌入
JS
放在
head
中,請把嵌入
JS
放在
CSS
頭部。
3
、使用
defer
(只支援
IE
)
4
、不要在嵌入的
JS
中呼叫執行時間較長的函式,如果一定要用,可以用
`setTimeout`
來呼叫
Javascript無阻塞載入具體方式
- 將指令碼放在底部。
<link>
還是放在head
中,用以保證在js
載入前,能加載出正常顯示的頁面。<script>
標籤放在</body>
前。 - 成組指令碼:由於每個
<script>
標籤下載時阻塞頁面解析過程,所以限制頁面的<script>
總數也可以改善效能。適用於內聯指令碼和外部指令碼。
- 非阻塞指令碼:等頁面完成載入後,再載入
js
程式碼。也就是,在window.onload
事件發出後開始下載程式碼。
(1)defer
屬性:支援IE4和fierfox3.5
更高版本瀏覽器
(2)動態指令碼元素:文件物件模型(DOM)允許你使用js動態建立HTML
的幾乎全部文件內容。程式碼如下:
<script>
var script=document.createElement("script");
script.type="text/javascript";
script.src="file.js";
document.getElementsByTagName("head")[0].appendChild(script);
</script>
此技術的重點在於:無論在何處啟動下載,檔案額下載和執行都不會阻塞其他頁面處理過程。即使在head裡(除了用於下載檔案的http連結)。
45.閉包相關問題?
46.js事件處理程式問題?
47.eval是做什麼的?
它的功能是把對應的字串解析成
JS
程式碼並執行;
應該避免使用
eval
,不安全,非常耗效能(
2
次,一次解析成
js
語句,一次執行)。
48.寫一個通用的事件偵聽器函式?
// event(
事件
)
工具集,來源:
github.com/markyun
markyun.Event = {
//
頁面載入完成後
readyEvent : function(fn) {
if (fn==null) {
fn=document;
}
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = fn;
} else {
window.onload = function() {
oldonload();
fn();
};
}
},
//
視能力分別使用
dom0||dom2||IE
方式
來繫結事件
//
引數:
操作的元素
,
事件名稱
,
事件處理程式
addEvent : function(element, type, handler) {
if (element.addEventListener) {
//
事件型別、需要執行的函式、是否捕捉
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent('on' + type, function() {
handler.call(element);
});
} else {
element['on' + type] = handler;
}
},
//
移除事件
removeEvent : function(element, type, handler) {
if (element.removeEnentListener) {
element.removeEnentListener(type, handler, false);
} else if (element.datachEvent) {