這是我在學習中的一些筆記,閉包、作用域、原型等等常考熱點,這些將以面試題的方式呈現給大家,希望大家批評指正。
1. 閉包
1. 涉及面試題:什麼是閉包?
閉包的定義其實很簡單:函式 A 內部有一個函式 B,函式 B 可以訪問到函式 A 中的變數,那麼函式 B 就是閉包。
function A(){
let a=1;
window.B=function(){
console.log(a)
}
}
A();
B();//1複製程式碼
很多人對於閉包的解釋可能是函式巢狀了函式,然後返回一個函式。其實這個解釋是不完整的,就比如我上面這個例子就可以反駁這個觀點。
在 JS 中,閉包存在的意義就是讓我們可以間接訪問函式內部的變數。
2. 經典面試題:迴圈中使用閉包解決`var `定義函式的問題;
for(var i=0;i<=5;i++){
setTimeout(function timer(){
console.log(i)
},i*1000)
}
console.log(i)複製程式碼
輸出結果:立即輸出一個6,然後每隔一秒輸出一個6;
首先因為 setTimeout
是個非同步函式,所以會先把迴圈全部執行完畢,這時候 i
就是 6 了,所以會輸出一堆 6。
解決辦法有3種,
第一種是利用閉包的方式:
for(var i=0;i<=5;i++){
(function(j){
setTimeout(function timer(){
console.log(j)
},j*1000)
})(i)
}複製程式碼
在上述程式碼中,我們首先使用了立即執行函式將 i
傳入函式內部,這個時候值就被固定在了引數 j
上面不會改變,當下次執行 timer
這個閉包的時候,就可以使用外部函式的變數 j
,從而達到目的。
第二種就是使用 setTimeout
的第三個引數,這個引數會被當成 timer
函式的引數傳入。
for(var i=0;i<=5;i++){
setTimeout(function timer(j){
console.log(j);
},i*1000,i)
}複製程式碼
第三種就是使用 let
定義 i
了來解決問題了,這個也是最為推薦的方式
for(let i=0;i<=5;i++){
setTimeout(function timer(){
console.log(i)
},i*1000)
}複製程式碼
2. JS作用域
1. js作用域(全域性變數,區域性變數)內部可以訪問外部,但外部的不能訪問內部的
var a=10;
function aaa(){
alert(a);
};
aaa();//10複製程式碼
function aaa(){
var a=10;
};
aaa();
console.log(a)//Uncaught ReferenceError: a is not defined複製程式碼
var a=10;
function aaa(){
console.log(a);//10
};
function bbb(){
var a=20;
aaa();
}
bbb();//10複製程式碼
function aaa(){
a=10;
}
aaa();
function aaa(){
var a=b=10;
}
aaa();
console.log(b)//10
console.log(a)//Uncaught ReferenceError: a is not defined複製程式碼
2. 不用var 定義變數時,會預設為是全域性變數(不規範,不推薦)
function aaa(){
a=10;
}
aaa();
function aaa(){
var a=b=10;
}
aaa();
console.log(b)
console.log(a)複製程式碼
3. 變數的查詢是就近原則去尋找,定義的var變數;
變數的宣告被提前到作用域頂部,賦值保留在原地,如下 domo ;
function aaa(){
console.log(a);//undefined
var a=20;
}
aaa(); 複製程式碼
var a=10;
function aaa(){
console.log(a);//undefined
var a=20;
}
aaa();複製程式碼
var a=10;
function aaa(a){
console.log(a);//10
var a=20; //因為 a 是形參,優先順序高於 var a; 所以 區域性變數a的宣告其實被忽略了。
}
aaa(a);複製程式碼
JS 基礎面試題
1.介紹下js中關於arguments 。 【考點:函式arguments】
在函式程式碼中,使用特殊物件 arguments,開發者
,就能訪問它們。
例如,在函式 sayHi() 中,第一個引數是 message。用 arguments[0] 也可以訪問這個值,即第一個引數的值(第一個引數位於位置 0,第二個引數位於位置 1,依此類推)。
因此,無需明確命名引數,就可以重寫函式:
function sayHi() {
if (arguments[0] == "bye") {
return;
}
alert(arguments[0]);
}複製程式碼
2.看以下JavaScript程式問:執行以上程式後,num的值為( D )【考點:資料型別】
var num;
num=5+true;
A、true B、false C、5 D、6複製程式碼
3、看以下JavaScript程式【考點:switch語句,break】
var x=prompt("請輸入1-5的數字","");
switch (x) {
case “1”:alert(“one”);
case “2”:alert(“two”);
case “3”:alert(“three”);
case “4”:alert(“four”);
case “5”:alert(“five”);
default:alert(“none”);
}複製程式碼
執行以上程式,在提示對話方塊中輸入“4”,依次彈出的對話方塊將輸出: ( B )
A、four,none B、four,five,none C、five D、five,none
4、分析下面的JavaScript程式碼段【考點:for迴圈】
a=new Array(2,3,4,5,6);
sum=0;
輸出結果是().(選擇一項)
for(i=1;i<a.length;i++ )
sum +=a[i];document.write(sum);
A. 20 B. 18 C. 14 D. 12複製程式碼
5、在HTML中,Location物件的()屬性用於設定或檢索URL的埠號。(B)
【考點:location物件】
A. hostname B. Port C. pathname D. href複製程式碼
6、分析下面的javascript程式碼: 【考點:+ 的用法,加法和連線符】
x=11;y="number";
m= x+y ;
m的值為(A)
A. 11number B. number C. 11 D. 程式報錯複製程式碼
7、setInterval("alert('welcome');",1000);【考點:定時器的用法】
這段程式碼的意思是(D)
A. 等待1000秒後,再彈出一個對話方塊
B. 等待1秒鐘後彈出一個對話方塊
C. 語句報錯,語法有問題 D.
每隔一秒鐘彈出一個對話方塊複製程式碼
8、分析下面的JavaScript程式碼段:【考點:Math物件的方法使用,round 四捨五入】
var a=15.49;document.write(Math.round(a));
輸出的結果是().(A)
A. 15 B. 16 C. 15.5 D. 15.4複製程式碼
9、分析如下的JavaScript程式碼片段, b的值為(C ) 【考點:parseInt取整】
Var a = 1.5,b;
b=parseInt(a);
A. 2 B. 0.5 C. 1 D. 1.5複製程式碼
10、在表單(form1)中有一個文字框元素(fname),用於輸入電話號碼,格式如:010-82668155,要求前3位是010,緊接一個“-”,後面是8位數字。要求在提交表單時,根據上述條件驗證該文字框中輸入內容的有效性,下列語句中,( A )能正確實現以上功能
【考點:substr() 擷取字串的使用,isNaN 判斷是否為數字】
A.var str= form1.fname.value;
if(str.substr(0,4)!="010-" ||str.substr(4).length!=8 || isNaN(parseFloat(str.substr(4))))
alert("無效的電話號碼!");
B.var str= form1.fname.value;
if(str.substr(0,4)!="010-" && str.substr(4).length!=8 && isNaN(parseFloat(str.substr(4))))
alert("無效的電話號碼!");
C.var str= form1.fname.value;
if(str.substr(0,3)!="010-" ||str.substr(3).length!=8 || isNaN(parseFloat(str.substr(3))))
alert("無效的電話號碼!");
D.var str= form1.fname.value;
if(str.substr(0,4)!="010-"&& str.substr(4).length!=8 && !isNaN(parseFloat(str.substr(4))))
alert("無效的電話號碼!");複製程式碼
11、以下哪個單詞不屬於javascript保留字:(b)
【考點:javascript保留字,防止命名出現使用保留字而產生錯誤】
A.with B.parent C.class D.void複製程式碼
12、請選擇結果為真的表示式:( C )
【考點:對null ,undefined,NaN的理解】
A.nullinstanceof Object(if(!(null instanceofObject))是真的)
B.null === undefined
C.null == undefined
D.NaN == NaN複製程式碼
13、以下哪個運算子不屬於邏輯運算子?( C )
【考點:邏輯運算子和位運算子】
1.A、&& B、|| C、^ D、!複製程式碼
14、下面定義變數中錯誤的是( D )。
【考點:變數定義規則】
A、 eee B、 _abc C、box_1 D、 2point複製程式碼
15、下面語句var x= -10, y; x=2*x; y=x+15;計算後y的結果是( C )。
【考點:四則運算】
A.-15 B、10 C、-5 D、5複製程式碼
16、下列表示式運算結果為真的是( D )。
【考點:邏輯運算】
A、1<2 && “5”! =5
B、2>2*1 || “5”= =5
C、2>2*1 &&5= =5
D、 1<2 && “5”= =5複製程式碼
17、以下程式段,執行的結果是( C )。
【考點:while迴圈,避免出現死迴圈,除非有需要】
var x=-1;
do{
x=x*x;
}
while(!x);
A、是死迴圈 B、迴圈執行二次 C、迴圈執行一次 D、有語法錯誤複製程式碼
18.執行語句for(i=1;i++<10; );後變數i的值是( C )。
【考點:for迴圈,什麼時候跳出迴圈】
A、9 B、10 C、11 D、不定複製程式碼
19、鍵盤事件中不包括的是( B )。【考點:鍵盤事件】
A、keydown B、keyover C、keypress D、keyup複製程式碼
20、執行以下指令碼語句在頁面輸出( true )。【考點:四則運算和邏輯運算綜合應用】
var a=3;
a+=8*2;
alert(a>10&&a<=20);複製程式碼
21、預測以下程式碼片段的輸出結果 var str ;( B )
alert(typeof str); 【考點:變數的定義和typeof 操作符的使用】A;string B:undefined C:Object D:String複製程式碼
22.以下哪項不屬於Javascript的特徵? 【考點:JavaScript語言特性】C
A.Javascript是一種指令碼語言
B.Javascript是事件驅動的
C.Javascript程式碼需要編譯以後才能執行
D.Javascript是獨立於平臺的複製程式碼
23.閱讀下面的JavaScript程式碼:
【考點:函式呼叫】B
function f(y) {
var x=y*y;
return x;
}
for(x=0;x< 5;x++) {
y=f(x);
document.writeln(y);
A.0 1 2 3 4 B.0 1 4 9 16 C.0 1 4 9 16 25 D.以上答案都不對複製程式碼
24、關於Javascript中陣列的說法中,不正確的是:(A)
【考點:陣列的理解,包括建立,長度,元素的型別等概念】
A.陣列的長度必須在建立時給定,之後便不能改變
B.由於陣列是物件,因此建立陣列需要使用new運算子
C.陣列內元素的型別可以不同
D.陣列可以在宣告的同時進行初始化複製程式碼
25、考察以下程式片段: 【考點:toFixed 保留小數位數的使用】
var n = new Number(3456);
alert(n.toFixed(2));
以下選項正確的是:( C
)A.輸出
34 B.輸出 56 C.輸出3456.00 D.輸出345600複製程式碼
26、察以下程式片段以下選項正確的是 ( C ) :
【考點:注意:如果 end 未被規定,那麼 slice() 方法會選取從 start 到陣列結尾的所有元素】
var str = “32px”;
var str1 = str.slice(-2);
alert(str);
alert(str1);
A依次輸出”px” “px”
B依次輸出”32” “32”
C依次輸出”32px” “px”
D依次輸出”32px” “32px”複製程式碼
27、考察以下程式片段以下選項正確的是( A )
【考點:字串的方法indexof的使用,之一返回的是下標】:
var str = “12px”;
var s = str.indexof(“2”);
alert(s);A.輸出
1 B.輸出 2 C.輸出 p D.輸出 12複製程式碼
28、在JavaScript中,下列哪段程式碼能夠在1秒之後執行表示式expression( D )
【考點:setTimeout 的使用,注意時間的表達,以毫秒計,1秒應寫為1000毫秒】
A.window.setTimeout(1000,expression);
B.window.setTimeout(expression,1);
C.window.setTimeout(1,expression);
D.window.setTimeout(expression,1000);複製程式碼
29、在JavaScript中,如果不指明物件直接呼叫某個方法,則該方法預設屬於哪個物件: (B)
【考點:方法的呼叫,一般如果沒有明確對用者,則是window物件】
A.document B.Window C.form D.Location複製程式碼
30、history從屬於window,下列能訪問前一頁面方法是:( D )
【考點:history物件使用】
A.back(-1) B.back(1) C.forward(1) D.go(-1)複製程式碼
31、有語句“var x=0;while(____) x+=2;”,要使while迴圈體執行10次,空白處的迴圈判定式應寫為:( C )
A.x<10 B.x<=10 C.x<20 D.x<=20複製程式碼
【考點:while迴圈】
32、以下( )表示式產生一個0~7之間(含0,7)的隨機整數.( C )
A.Math.floor(Math.random()*6)
B.Math.floor(Math.random()*7)
C.Math. floor(Math.random()*8)
D.Math.ceil(Math.random()*8)複製程式碼
【考點:隨機數產生,注意左包右不包,隨機數日後會經常用到,需熟練掌握】
33、在HTML頁面中包含如下所示程式碼,則編寫Javascript函式判斷是否按下鍵盤上的Enter鍵正確的編碼是(C)
【考點:鍵盤事件,獲取按鍵編碼 event.keyCode】
<input name=”password” type=”text” onkeydown=”myKeyDown()”>
A. function myKeyDown(){
if (window.keyCode==13)
alert(“你按下了Enter鍵”);
B. function myKeyDown(){
if (document.keyCode==13)
alert(“你按下了Enter鍵”);
C. function myKeyDown(){
if (event.keyCode==13)
alert(“你按下了Enter鍵”);
D. function myKeyDown(){
if (keyCode==13)複製程式碼
34、在HTML頁面上,當按下鍵盤上的任意一個鍵時都會觸發Javascript的( D)事件(
A.onFocus B.onBlur C.onSubmit D.onKeyDown複製程式碼
35、看以下JavaScript程式 【考點: ++ 運算子的使用,什麼時候先加後賦值,什麼時候先賦值後++】
var x,y;
x=10;
y=x++;
執行以上程式後,變數y的值為 10 。複製程式碼
36、看以下JavaScript程式【考點: && 運算子】
var i,j;
i=0;
j=i&&(++i);
執行以上程式後,變數i的值為 0 。複製程式碼
37、看以下JavaScript程式 【考點: do while 語句,先執行一次,在判斷條件】
var i;
i=8;
do{
i++;
}
while(i>100);
執行以上程式後,變數i的值為 9 。複製程式碼
38、看以下JavaScript程式 【考點: continue 和break的使用】
for(var i=1;i<=10;i++){
if(i==5)
continue;
if(i==8)
break;
alert(i);
}
執行以上程式後,彈出的對話方塊依次輸出的值為 1,2,3,4,6,7 。複製程式碼
39、編寫程式實現去除陣列重複元素【考點:程式邏輯,簡單的演算法實現功能,一題多解】
function
unique1(array){
var n= []; //一個新的臨時陣列
//遍歷當前陣列
for(vari = 0; i < array.length; i++){
//如果當前陣列的第i已經儲存進了臨時陣列,那麼跳過, 否則把當前項push到臨時陣列裡面
if(n.indexOf(array[i]) == -1)
n.push(array[i]);
}
return n;
}複製程式碼
40、
var k;
for(var i=0;i<5 ;i++ ){
for (var j=0;j<10 ;j++ ){
k=i+j;
}
}
alert(k) //13
【考點:for迴圈,注意何時跳出迴圈】複製程式碼
41、
var a=0; test(); function test(){ var a = 6 b() } function b(){ alert(a) } 結果為: 0 【考點:變數的作用域,此處容易出錯】複製程式碼
42 、
function foo(){alert("aaaa");a = setTimeout(foo(),100);}foo(); 無限迴圈複製程式碼
【考點:setTimeout,以及遞迴呼叫】
43、window物件的方法中,( A )方法是用於彈出確認對話方塊,可讓選擇“確定”或“取消” 【考點:confirm】
A、confirm() B、alert() C、prompt() D、open()複製程式碼
44、用JavaScript實現開啟一個新視窗,地址為abc.html,正確的方法是(A)【考點:BOM 中open()方法】
A、window.open(“abc.html”,“”,“”);
B、window.open(“”,“abc.html”,“”);
C、window.open(“”,“”,“abc.html”);
D、window.open(“”,“”,“”);複製程式碼
45、在JavaScript程式中加入註釋,方法有(AB)【js註釋】
A、//註釋內容 B、/*註釋內容*/
C、/註釋內容 D、/*註釋內容複製程式碼
46、以下JavaScript變數名不合法的有(ABC) 【變數名,識別符號規則】
A、4Myvariable B、My@variable C、function D、Myvariable4複製程式碼
47、看下列程式碼,將會輸出什麼?(變數宣告提升)
var foo = 1;function(){
console.log(foo);
var foo = 2;
console.log(foo);
}
答案:輸出undefined
和 2。【變數提升】複製程式碼
48、求y和z的值是多少 兩個undefined
var x = 1;
var y = 0;
var z = 0;
function add(n){n=n+1;
}
y = add(x);
function add(n){
n=n+3;
}
z = add(x);複製程式碼
49、寫出函式DateDemo的返回結果,系統時間假定為今天
function DateDemo(){
var d, s="今天日期是:";
d = new Date(); s += d.getMonth() +"/";
s += d.getDate() +"/";
s += d.getYear();
return s;
}
結果:今天日期是:當前系統日期複製程式碼
50、寫出程式執行的結果?
for(i=0, j=0; i<10, j<6; i++, j++){
k = i + j;
}複製程式碼
結果:10(小心陷阱)
JS 高階 面試題
1、談談你對Ajax的理解?(概念、特點、作用)
AJAX全稱為“Asynchronous JavaScript And XML”(非同步JavaScript和XML) 是指一種建立互動式網頁應用的開發技術、改善使用者體驗,實現無重新整理效果。優點
a、不需要外掛支援
b、優秀的使用者體驗
c、提高Web程式的效能
d、減輕伺服器和頻寬的負擔
缺點
a、瀏覽器對XMLHttpRequest物件的支援度不足,幾乎所有瀏覽器現在都支援
b、破壞瀏覽器“前進”、“後退”按鈕的正常功能,可以通過簡單的外掛彌補
c、對搜尋引擎的支援不足
2. 什麼是跨域,如何實現跨域訪問?
跨域是指不同域名之間相互訪問。JavaScript同源策略的限制,A域名下的JavaScript無法操作B或是C域名下的物件
實現:
(1) JSONP跨域:利用script指令碼允許引用不同域下的js實現的,將回撥方法帶入伺服器,返回結果時回撥。
(2) 跨域資源共享(CORS)
跨域資源共享(CORS)是一種網路瀏覽器的技術規範,它為Web伺服器定義了一種方式,允許網頁從不同的域訪問其資源。
CORS與JSONP相比:
a、 JSONP只能實現GET請求,而CORS支援所有型別的HTTP請求。
b、 使用CORS,開發者可以使用普通的XMLHttpRequest發起請求和獲得資料,比起JSONP有更好的錯誤處理。
c、 JSONP主要被老的瀏覽器支援,它們往往不支援CORS,而絕大多數現代瀏覽器都已經支援了CORS。
3. get和post的區別,何時使用post?
(1)、get 是從伺服器上獲取資料,post
是向伺服器傳送資料。 get 請求返回 request -
URI 所指出的任意資訊。
Post 請求用來傳送電子郵件、新聞或傳送能由互動使用者填寫的表格。這是唯一需要在請求中傳送body的請求。使用Post請求時需要在報文首部 Content - Length 欄位中指出body的長度。
(2)、get 是把引數資料佇列加到提交表單的ACTION屬性所指的URL中,值和表單內各個欄位一一對應,在URL中可以看到。post是通過HTTP
post機制,將表單內各個欄位與其內容放置在HTML HEADER內一起傳送到ACTION屬性所指的URL地址,使用者看不到這個過程。
(3)、對於 get 方式,伺服器端用Request.QueryString獲取變數的值,對於 post 方式,伺服器端用Request.Form獲取提交的資料。
(4)、get 傳送的資料量較小,不能大於2KB。post 傳送的資料量較大,一般被預設為不受限制。但理論上,IIS4中最大量為80KB,IIS5中為100KB。 用IIS過濾器的只接受get引數,所以一般大型搜尋引擎都是用get方式。
(5)get安全性非常低,post 安全性相對較高。如果這些資料是中文資料而且是非敏感資料,那麼使用get;如果使用者輸入的資料不是中文字元而且包含敏感資料,那麼還是使用 post 為好。
4. 對比 Flash 與 ajax 哪個好,在使用中如何取捨?
Ajax的優勢:
(1)、可搜尋性
普通的文字網頁會更有利於SEO。文字內容是搜尋引擎容易檢索的,而繁瑣的swf位元組碼卻是搜尋引擎不願觸及的。雖然Google等一些大型的搜尋引擎可以檢索SWF內部的內容,但是仍然有很多麻煩存在。
(2)、開放性
Flash常年以來被Macromedia看的很死。包括Flex、FMS等輔佐技術一直都需要昂貴的安裝、維護費用。而JS則沒有這樣的麻煩。沒有人願意承擔法律和版權的風險。費用Flash開發是很昂貴的,因為FlashIDE等環境都是要收費的.而Ajax則不同.雖然有一些便宜的生成swf的工具,但是他們的工能實在無法滿足複雜需求。
(3)、易用性
Ajax程式有更好的易用性。由於中間有一層Flashplayer代理層,因此許多輔助功能無法被Flash靈活利用。而且Flash在一些方面有著不好的口碑。比如彈出廣告、比如惡意程式碼。
(4)、易於開發
人們開發複雜的Ajax和Flash應用程式時,都會藉助一些高階的開發工具。普遍來說,Ajax的開發包比Flash簡便、容易。
Flash的優勢:
(1)、多媒體處理
Flash在音訊、視訊等多媒體領域相比HTML有絕對的優勢。現在幾乎所有的網站都包含有Flash內容。
(2)、相容性
相容性好:由於通過了唯一的FlashPlayer“代理”。人們不必像除錯JS那樣,在不同的瀏覽器中除錯程式。
(3)、向量圖型
這是Flash最大的優勢,同樣處在這一領域的SVG、Canvas element以及Direct完全不能與Flash相比。
(4)、客戶端資源排程
Flash能夠更容易的呼叫瀏覽器以外的外部資源。比如攝像頭、麥克風等。然而這是普通的HTML無法完成的。但是這也許是一個缺點(為什麼呢?)
Ajax的劣勢:
(1)、它可能破壞瀏覽器的後退功能
(2)、使用動態頁面更新使得使用者難於將某個特定的狀態儲存到收藏夾中
,不過這些都有相關方法解決。
Flash的劣勢:
(1)二進位制格式
(2)格式私有
(3)flash 檔案經常會很大,使用者第一次使用的時候需要忍耐較長的等待時間
(4)效能問題
5.同步和非同步的區別?
舉個例子:普通B/S模式(同步)AJAX技術(非同步)
同步:提交請求->等待伺服器處理->處理完畢返回 這個期間客戶端瀏覽器不能幹任何事
非同步: 請求通過事件觸發->伺服器處理(這是瀏覽器仍然可以作其他事情)->處理完畢
ajax.open方法中,第3個引數是設同步或者非同步。
prototype等js類庫一般都預設為非同步,即設為true。先說下同步的情況下,js會等待請求返回,獲取status。不需要onreadystatechange事件處理函式。而非同步則需要 onreadystatechange事件處理,且值為4再正確處理下面的內容。
//同步傳輸模式
function RequestByGet(nProducttemp,nCountrytemp) {
var xmlhttp
if (window.XMLHttpRequest) {
//isIE = false;
xmlhttp = new XMLHttpRequest();
}else if (window.ActiveXObject) {
//isIE = true;
xmlhttp = new
ActiveXObject("Microsoft.XMLHTTP");
}
//Web page location.
var URL="http://www.baidu.com/;
xmlhttp.open("GET",URL, false);
//xmlhttp.SetRequestHeader("Content-Type","text/html;charset="utf-8")
xmlhttp.send(null);
var result = xmlhttp.status;
//OK
if(result==200){
document.getElementById("div_RightBarBody").innerHTML=xmlhttp.responseText;
}
xmlhttp = null;
}複製程式碼
//非同步傳輸模式
var xmlhttp
function RequestByGet(nProducttemp,nCountrytemp) {
if (window.XMLHttpRequest) {
//isIE = false;
xmlhttp = new XMLHttpRequest();
} else if (window.ActiveXObject) {
//isIE = true;
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
//Web page location.
var URL="http://www.baidu.com/";
xmlhttp.open("GET",URL, true);
xmlhttp.onreadystatechange = handleResponse;
//xmlhttp.SetRequestHeader("Content-Type","text/html;charset=UTF-8")
xmlhttp.send(null);
}
function handleResponse() {
if(xmlhttp.readyState == 4 && xmlhttp.status==200) {
document.getElementById("div_RightBarBody").innerHTML=xmlhttp.responseText;
xmlhttp = null;
}
} 複製程式碼
6.根據你的理解,請簡述JavaScript指令碼的執行原理?
7. 說說你對json的理解?
回答一:
JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。
它是基於JavaScript的一個子集。資料格式簡單, 易於讀寫, 佔用頻寬小.
json簡單說就是javascript中的物件和陣列,所以這兩種結構就是物件和陣列。
a、JSON物件:以“{”開始,以“}”結束,裡面則是一系列的鍵(key)值(value)對,鍵和值用“:”分開,每對鍵值對之間用“,”分開。參考以下語法結構:{key1:value1,key2:value2,key3:value3…}其中鍵(key)是字串,而值(value)可以是字串,數值,true,false,null,物件或陣列,也就是說某個鍵(key)的值(value)可以是一個陣列,陣列裡面又是一些JSON物件,這種表示稍微複雜一些,但是參照這些理解可以很容易分辨出來。
b、JSON陣列:以”[”開始,”]”結束,如同程式語言一樣,例如C#,Button[] btnArray,則BtnArray是一個Button型別的陣列,裡面就存放Button型別的物件,那麼JSON陣列也一樣,裡面存放的也是JSON物件.
回答二:
a、JSON 指的是 JavaScript 物件表示法(JavaScript Object Notation)
b、JSON 是輕量級的文字資料交換格式,並不是程式語言
c、JSON 獨立於語言存在
d、JSON 具有自我描述性,更易理解
e、JSON 可以將 JavaScript 物件中表示的一組資料轉換為字串,然後就可以在函式之間輕鬆地傳遞這個字串,或者在非同步應用程式中將字串從 Web 客戶機傳遞給伺服器端程式。這個字串看起來有點兒古怪,但是JavaScript很容易解釋它,而且 JSON 可以表示比"名稱
/ 值對"更復雜的結構。例如,可以表示陣列和複雜的物件,而不僅僅是鍵和值的簡單列表
8.談談你對閉包的理解?
(1)、使用閉包主要是為了設計私有的方法和變數。閉包的優點是可以避免全域性變數的汙染,缺點是閉包會常駐記憶體,會增大記憶體使用量,使用不當很容易造成記憶體洩露。(2)、閉包有三個特性:
a、函式巢狀函式
b、函式內部可以引用外部的引數和變數
c、引數和變數不會被垃圾回收機制回收
9. 談談你This物件的理解?
回答一:
(1)、js的this指向是不確定的,也就是說是可以動態改變的。call/apply 就是用於改變this指向的函式,這樣設計可以讓程式碼更加靈活,複用性更高
(2)、this 一般情況下,都是指向函式的擁有者。
(3)、在函式自執行裡,this
指向的是 window 物件。
擴充套件:關於this,還有一個地方比較讓人模糊的是在dom事件裡,通常有如下3種情況:
a、使用標籤屬性註冊事件,此時this指向的是window物件。
b、對與a,要讓this指向input,可以將this作為引數傳遞。
c、使用addEventListener等註冊事件。此時this也是指向 input。
回答二:
(1)、處於全域性作用域下的this:在全域性作用域下this預設指向window物件。
this;/*window*/
var a = {name:this}/*window*/
var b =[this];/*window*/複製程式碼
(2)、處在函式中的this,又分為以下幾種情況:
a、一般定義的函式,然後一般的執行:this還是預設指向window。
var a = function(){
console.log(this);
}
a();/*window*/複製程式碼
b、一般定義,用new呼叫執行:這時候讓this指向新建的空物件,我們才可以給空物件初始化自有變數
var a = function(){
console.log(this);
}
new a();/*新建的空物件*/複製程式碼
c、作為物件屬性的函式,呼叫時:這時候this指向呼叫f函式的a物件。
var a = {
f:function(){
console.log(this)
}
}
a.f();/*a物件*/複製程式碼
(3)、通過call()和apply()來改變this的預設引用:
var b = {id: 'b'};
var a = {
f:function(){
console.log(this)
}
}
a.f.call(b);/*window*/複製程式碼
所有函式物件都有的call方法和apply方法,它們的用法大體相似,f.call(b)的意思是,執行f函式,並將f函式執行期活動物件裡的this指向b物件,這樣標示符解析時,this就會是b物件了。不過呼叫函式是要傳參的。所以,f.call(b, x, y); f.apply(b, [x, y]);以上就是用call方法執行f函式,與用apply方法執行f函式時傳參方式,它們之間的差異,大家一目瞭然:apply通過陣列的方式傳遞引數,call通過一個個的形參傳遞引數。
(4)、一些函式特殊執行情況this的指向問題:
a、setTimeout()和setInverval():
var a = function(){
console.log(this);
}
setTimeout(a,0);/*window*/複製程式碼
setInterval()類似。
b、dom模型中觸發事件的回撥方法執行中活動物件裡的this指向該dom物件。
10. JavaScript物件的幾種建立方式?
(1)通過new 方法
var obj = new Object(); 複製程式碼
(2) 工廠模式
function Parent(){
var Child = new Object();
Child.name="欲淚成雪";
Child.age="20";
return Child;
};
var x = Parent()複製程式碼
引用該物件的時候,這裡使用的是 var x = Parent()而不是 var x = new Parent();因為後者會可能出現很多問題(前者也成為工廠經典方式,後者稱之為混合工廠方式),不推薦使用new的方式使用該物件
(2)建構函式方式
function Parent(){
this.name="欲淚成雪";
this.age="20";
};
var x =new Parent();複製程式碼
(3) 原型模式
function Parent(){};
Parent.prototype.name="欲淚成雪";
Parent.prototype.age="20";
var x =new Parent();複製程式碼
(4)混合的建構函式,原型方式(推薦)
function Parent(){
this.name="欲淚成雪";
this.age=22;
};
Parent.prototype.lev=function(){
return
this.name;
};
var x =new Parent();複製程式碼
(5)動態原型方式
function Parent(){
this.name="欲淚成雪";
this.age=22;
if(typeofParent._lev=="undefined"){
Parent.prototype.lev=function(){
return this.name;
}
Parent._lev=true;
}}
var x =new Parent();複製程式碼
11. 請寫出js記憶體洩漏的問題?
回答一:
(1)、IE7/8 DOM物件或者ActiveX物件迴圈引用導致記憶體洩漏
a、多個物件迴圈引用
b、迴圈引用自己
(2)、基礎的DOM洩漏
當原有的DOM被移除時,子結點引用沒有被移除則無法回收。
(3)、timer定時器洩漏
這個時候你無法回收buggyObject,解決辦法,先停止timer然後再回收
回答二:
記憶體洩漏指任何物件在您不再擁有或需要它之後仍然存在。
垃圾回收器定期掃描物件,並計算引用了每個物件的其他物件的數量。如果一個物件的引用數量為
0(沒有其他物件引用過該物件),或對該物件的惟一引用是迴圈的,那麼該物件的記憶體即可回收。
setTimeout
的第一個引數使用字串而非函式的話,會引發記憶體洩漏。
閉包、控制檯日誌、迴圈(在兩個物件彼此引用且彼此保留時,就會產生一個迴圈)也會引發記憶體洩漏問題。
12. 請你解釋一下事件冒泡機制?
a、在一個物件上觸發某類事件(比如單擊onclick事件),如果此物件定義了此事件的處理程式,那麼此事件就會呼叫這個處理程式,如果沒有定義此事件處理程式或者事件返回true,那麼這個事件會向這個物件的父級物件傳播,從裡到外,直至它被處理(父級物件所有同類事件都將被啟用),或者它到達了物件層次的最頂層,即document物件(有些瀏覽器是window)。
b、冒泡型事件:事件按照從最特定的事件目標到最不特定的事件目標(document物件)的順序觸發
c、js冒泡機制是指如果某元素定義了事件A,如click事件,如果觸發了事件之後,沒有阻止冒泡事件,那麼事件將向父級元素傳播,觸發父類的click函式。
//阻止冒泡時間方法,相容ie(e.cancleBubble)和ff(e.stopProgation)
function stopBubble(e){
var evt = e||window.event;
evt.stopPropagation?evt.stopPropagation():(evt.cancelBubble=true);//阻止冒泡
evt.preventDefault
}複製程式碼
13. 說說你對Promise的理解?
ES6 原生提供了
Promise 物件。
所謂 Promise,就是一個物件,用來傳遞非同步操作的訊息。它代表了某個未來才會知道結果的事件(通常是一個非同步操作),並且這個事件提供統一的 API,可供進一步處理。
Promise 物件有以下兩個特點。
(1)、物件的狀態不受外界影響。Promise 物件代表一個非同步操作,有三種狀態:Pending(進行中)、Resolved(已完成,又稱 Fulfilled)和 Rejected(已失敗)。只有非同步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態。這也是 Promise 這個名字的由來,它的英語意思就是「承諾」,表示其他手段無法改變。
(2)、一旦狀態改變,就不會再變,任何時候都可以得到這個結果。Promise 物件的狀態改變,只有兩種可能:從 Pending 變為 Resolved 和從 Pending 變為 Rejected。只要這兩種情況發生,狀態就凝固了,不會再變了,會一直保持這個結果。就算改變已經發生了,你再對 Promise 物件新增回撥函式,也會立即得到這個結果。這與事件(Event)完全不同,事件的特點是,如果你錯過了它,再去監聽,是得不到結果的。
有了 Promise 物件,就可以將非同步操作以同步操作的流程表達出來,避免了層層巢狀的回撥函式。此外,Promise 物件提供統一的介面,使得控制非同步操作更加容易。
Promise 也有一些缺點。首先,無法取消 Promise,一旦新建它就會立即執行,無法中途取消。其次,如果不設定回撥函式,Promise 內部丟擲的錯誤,不會反應到外部。第三,當處於 Pending 狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)。
14. 談談你對Javascript垃圾回收機制的理解?
(1)、標記清除(mark and sweep)
這是`JavaScript`最常見的垃圾回收方式,當變數進入執行環境的時候,比如函式中宣告一個變數,垃圾回收器將其標記為“進入環境”,當變數離開環境的時候(函式執行結束)將其標記為“離開環境”。
垃圾回收器會在執行的時候給儲存在記憶體中的所有變數加上標記,然後去掉環境中的變數以及被環境中變數所引用的變數(閉包),在這些完成之後仍存在標記的就是要刪除的變數了
(2)、引用計數(reference counting)
在低版本`IE`中經常會出現記憶體洩露,很多時候就是因為其採用引用計數方式進行垃圾回收。引用計數的策略是跟蹤記錄每個值被使用的次數,當宣告瞭一個
變數並將一個引用型別賦值給該變數的時候這個值的引用次數就加1,如果該變數的值變成了另外一個,則這個值得引用次數減1,當這個值的引用次數變為0的時 候,說明沒有變數在使用,這個值沒法被訪問了,因此可以將其佔用的空間回收,這樣垃圾回收器會在執行的時候清理掉引用次數為0的值佔用的空間。
在IE中雖然`JavaScript`物件通過標記清除的方式進行垃圾回收,但BOM與DOM物件卻是通過引用計數回收垃圾的,也就是說只要涉及BOM及DOM就會出現迴圈引用問題。
15. 說說你對原型(prototype)理解?
JavaScript是一種通過原型實現繼承的語言與別的高階語言是有區別的,像java,C#是通過型別決定繼承關係的,JavaScript是的動態的弱型別語言,總之可以認為JavaScript中所有都是物件,在JavaScript中,原型也是一個物件,通過原型可以實現物件的屬性繼承,JavaScript的物件中都包含了一個" prototype"內部屬性,這個屬性所對應的就是該物件的原型。
"prototype"作為物件的內部屬性,是不能被直接訪問的。所以為了方便檢視一個物件的原型,Firefox和Chrome核心的JavaScript引擎中提供了"__proto__"這個非標準的訪問器(ECMA新標準中引入了標準物件原型訪問器"Object.getPrototype(object)")。
原型的主要作用就是為了實現繼承與擴充套件物件。
16. typeof與instanceof的區別是什麼?
在 JavaScript 中,判斷一個變數的型別可以用typeof
(1)、數字型別, typeof 返回的值是
number。比如說:typeof(1),返回值是number
(2)、字串型別, typeof 返回的值是 string。比如typeof("123")返回值是string。
(3)、布林型別, typeof 返回的值是 boolean 。比如typeof(true)返回值是boolean。
(4)、物件、陣列、null 返回的值是 object 。比如typeof(window),typeof(document),typeof(null)返回的值都是object。
(5)、函式型別,返回的值是 function。比如:typeof(eval),typeof(Date)返回的值都是function。
(6)、不存在的變數、函式或者undefined,將返回undefined。比如:typeof(abc)、typeof(undefined)都返回undefined。
在JavaScript 中,instanceof用於判斷某個物件是否被另一個函式構造。
使用
typeof 運算子時採用引用型別儲存值會出現一個問題,無論引用的是什麼型別的物件,它都返回
"object"。ECMAScript 引入了另一個 Java 運算子 instanceof 來解決這個問題。instanceof 運算子與 typeof 運算子相似,用於識別正在處理的物件的型別。與 typeof 方法不同的是,instanceof 方法要求開發者明確地確認物件為某特定型別。
17. 請簡要說說你對Javascript物件導向的理解?
為了說明 JavaScript 是一門徹底的物件導向的語言,首先有必要從物件導向的概念著手 , 探討一下物件導向中的幾個概念:
a、一切事物皆物件
b、物件具有封裝和繼承特性
c、物件與物件之間使用訊息通訊,各自存在資訊隱藏
以這三點做為依據,C++ 是半物件導向半程式導向語言,因為,雖然他實現了類的封裝、繼承和多型,但存在非物件性質的全域性函式和變數。Java、C# 是完全的面嚮物件語言,它們通過類的形式組織函式和變數,使之不能脫離物件存在。但這裡函式本身是一個過程,只是依附在某個類上。
然而,物件導向僅僅是一個概念或者程式設計思想而已,它不應該依賴於某個語言存在。比如 Java 採用物件導向思想構造其語言,它實現了類、繼承、派生、多型、介面等機制。但是這些機制,只是實現物件導向程式設計的一種手段,而非必須。換言之,一門語言可以根據其自身特性選擇合適的方式來實現物件導向。所以,由於大多數程式設計師首先學習或者使用的是類似 Java、C++ 等高階編譯型語言(Java
雖然是半編譯半解釋,但一般做為編譯型來講解),因而先入為主地接受了“類”這個物件導向實現方式,從而在學習指令碼語言的時候,習慣性地用類式面嚮物件語言中的概念來判斷該語言是否是面嚮物件語言,或者是否具備物件導向特性。這也是阻礙程式設計師深入學習並掌握 JavaScript 的重要原因之一。
JavaScript 語言是通過一種叫做 原型(prototype)的方式來實現物件導向程式設計的。下面就來討論 基於類的(class-based)物件導向和 基於原型的 (prototype-based) 物件導向這兩種方式在構造客觀世界的方式上的差別。
基於類的物件導向和基於原型的物件導向方式比較,在基於類的物件導向方式中,物件(object)依靠類(class)來產生。而在基於原型的物件導向方式中,物件(object)則是依靠構造器(constructor)利用原型(prototype)構造出來的。舉個客觀世界的例子來說明二種方式認知的差異。例如工廠造一輛車,一方面,工人必須參照一張工程圖紙,設計規定這輛車應該如何製造。這裡的工程圖紙就好比是語言中的
類 (class),而車就是按照這個 類(class)製造出來的;另一方面,工人和機器 ( 相當於 constructor) 利用各種零部件如發動機,輪胎,方向盤 ( 相當於 prototype 的各個屬性 ) 將汽車構造出來。
事實上關於這兩種方式誰更為徹底地表達了物件導向的思想,目前尚有爭論。但認為原型式物件導向是一種更為徹底的物件導向方式,理由如下:
(1)、首先,客觀世界中的物件的產生都是其它實物物件構造的結果,而抽象的“圖紙”是不能產生“汽車”的,也就是說,類是一個抽象概念而並非實體,而物件的產生是一個實體的產生;
(2)、其次,按照一切事物皆物件這個最基本的物件導向的法則來看,類 (class) 本身並不是一個物件,然而原型方式中的構造器 (constructor)
和原型 (prototype) 本身也是其他物件通過原型方式構造出來的物件。
(3)、再次,在類式面嚮物件語言中,物件的狀態 (state) 由物件例項 (instance) 所持有,物件的行為方法 (method) 則由宣告該物件的類所持有,並且只有物件的結構和方法能夠被繼承;而在原型式面嚮物件語言中,物件的行為、狀態都屬於物件本身,並且能夠一起被繼承(參考資源),這也更貼近客觀實際。
(4)、最後,類式面嚮物件語言比如 Java,為了彌補無法使用程式導向語言中全域性函式和變數的不便,允許在類中宣告靜態
(static) 屬性和靜態方法。而實際上,客觀世界不存在所謂靜態概念,因為一切事物皆物件!而在原型式面嚮物件語言中,除內建物件 (build-in object) 外,不允許全域性物件、方法或者屬性的存在,也沒有靜態概念。
所有語言元素 (primitive) 必須依賴物件存在。但由於函式式語言的特點,語言元素所依賴的物件是隨著執行時 (runtime) 上下文 context變化而變化的,具體體現在this指標的變化。正是這種特點更貼近“萬物皆有所屬,宇宙乃萬物生存之根本”的自然
18. 你對JavaScript函式的理解是?
javascript中的函式就是物件,物件就是“鍵/值”對的集合並擁有一個連線到原型對隱藏連線。
(1)、引數物件 (arguments)
第一個函式中有一個預設物件叫arguments,類似陣列,但不是陣列,該物件是傳遞給函式的引數。
(2)、建構函式
在javascript中物件建構函式可以建立一個物件。
(3)、函式呼叫
a、call:呼叫一個物件的一個方法,以另一個物件替換當前物件
b、apply:應用某一物件的一個方法,用另一個物件替換當前物件,與call類似。
c、caller:在一個函式呼叫另一個函式時,被呼叫函式會自動生成一個caller屬性,指向呼叫它的函式物件。如果該函式當前未被呼叫,或並非被其他函式呼叫,則caller為null。
d、Callee:當函式被呼叫時,它的arguments.callee物件就會指向自身,也就是一個
對自己的引用。
19. 簡要說說什麼是IIFE?它有什麼作用?
IIFE即Immediately-Invoked Function Expression,立即執行函式表示式, 立即執行的函式表示式的執行括號應該寫在外包括號內。雖然寫在內還是寫在外都是有效的,但寫在內使得整個表示式看起來更像一個整體,因此推薦這麼做。
//最常用的兩種寫法
(function(){ /* code */ }()); // 老師推薦寫法
(function(){ /* code */ })(); // 當然這種也可以
// 括號和JS的一些操作符(如 =&& || ,等)可以在函式表示式和函式宣告上消除歧義
// 如下程式碼中,解析器已經知道一個是表示式了,於是也會把另一個預設為表示式
// 但是兩者交換則會報錯
var i = function(){
return 10;
}();
true && function(){ /* code */
}();0, function(){ /* code */ }();
// 如果你不怕程式碼晦澀難讀,也可以選擇一元運算子!function(){
/* code */
}();
~function(){
/* code */
}();
-function(){
/* code */
}();
+function(){
/* code */
}();
// 你也可以這樣
new function(){ /* code */ }
new function(){ /* code */ }() // 帶參複製程式碼
IIFE的作用
(1)、提高效能:減少作用域查詢時間。使用IIFE的一個微小的效能優勢是通過匿名函式的引數傳遞常用全域性物件window、document、jQuery,在作用域內引用這些全域性物件。JavaScript直譯器首先在作用域內查詢屬性,然後一直沿著鏈向上查詢,直到全域性範圍。將全域性物件放在IIFE作用域內提升js直譯器的查詢速度和效能。
(2)、壓縮空間:通過引數傳遞全域性物件,壓縮時可以將這些全域性物件匿名為一個更加精簡的變數名
(3)、避免衝突:匿名函式內部可以形成一個塊級的私有作用域。
(4)、依賴載入:可以靈活的載入第三方外掛,當然使用模組化載入更好(AMD,CMD)
20. 談談你對Function與Object的理解?
Function
函式就是物件,代表函式的物件就是函式物件。所有的函式物件是被Function這個函式物件構造出來的。Function是最頂層的構造器。它構造了系統中所有的物件,包括使用者自定義物件,系統內建物件,甚至包括它自已。這也表明Function具有自舉性(自已構造自己的能力)。這也間接決定了Function的call和constructor邏輯相同。每個物件都有一個
constructor 屬性,用於指向建立其的函式物件。
a、函式與物件具有相同的語言地位
b、沒有類,只有物件
c、函式也是一種物件,所謂的函式物件
d、物件是按引用來傳遞的
Object
對於Object它是最頂層的物件,所有的物件都將繼承Object的原型,但是你也要明確的知道Object也是一個函式物件,所以說Object是被Function構造出來的。
21、JavaScript 原型鏈
22. 請指出 JavaScript中的本地物件、內建物件、宿主物件的區別?
(1)、本地物件
ECMA-262
把本地物件(native
object)定義為“獨立於宿主環境的
ECMAScript 實現提供的物件”。
再來看一下,“本地物件”包含哪些內容:
Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError
由此可以看出,簡單來說,本地物件就是
ECMA-262 定義的類(引用型別)。
(2)、內建物件
ECMA-262 把內建物件(built-in object)定義為“由 ECMAScript 實現提供的、獨立於宿主環境的所有物件,在 ECMAScript 程式開始執行時出現”。這意味著開發者不必明確例項化內建物件,它已被例項化了。
同樣是“獨立於宿主環境”。根據定義我們似乎很難分清“內建物件”與“本地物件”的區別。而ECMA-262 只定義了兩個內建物件,即 Global 和 Math (它們也是本地物件,根據定義,每個內建物件都是本地物件)。
如此就可以理解了。內建物件是本地物件的一種。而其包含的兩種物件中,Math物件我們經常用到,可這個Global物件是啥東西呢?
Global物件是ECMAScript中最特別的物件,因為實際上它根本不存在,但大家要清楚,在ECMAScript中,不存在獨立的函式,所有函式都必須是某個物件的方法。類似於isNaN()、parseInt()和parseFloat()方法等,看起來都是函式,而實際上,它們都是Global物件的方法。
(3)、宿主物件
由ECMAScript實現的宿主環境提供的物件,即我們網頁的執行環境(作業系統和瀏覽器),所有的BOM和DOM都是宿主物件。
宿主環境提供的全域性方法:
alert、confirm、prompt、write、writeln(後面的兩種是document的方法)
內建物件是本地物件的一種,本地物件時由官方定義的,而宿主物件相當於由自己定義的物件、DOM物件和BOM物件組成的
23. 請解釋一下變數宣告提升?
a、變數定義
可以使用var定義變數,變數如果沒有賦值,那變數的初始值為undefined。
b、變數作用域
變數作用域指變數起作用的範圍。變數分為全域性變數和區域性變數。全域性變數在全域性都擁有定義;而區域性變數只能在函式內有效。
在函式體內,同名的區域性變數或者引數的優先順序會高於全域性變數。也就是說,如果函式記憶體在和全域性變數同名的區域性變數或者引數,那麼全域性變數將會被區域性變數覆蓋。 所有不使用var定義的變數都視為全域性變數。
24. 規避javascript多人開發函式重名問題
名稱空間
封閉空間
js模組化mvc(資料層、表現層、控制層)
seajs
變數轉換成物件的屬性
物件化
25. javascript物件導向中繼承實現
function Person(name){
this.name = name;
}
Person.prototype.showName = function(){
alert(this.name);
}
function Worker(name, job){
Person.apply(this,arguments)
this.job = job;
}
for(var i in Person.prototype){
Worker.prototype =
Person.prototype;
}
new Worker('sl', 'coders').showName();複製程式碼
26. 寫出3個使用this的典型應用
事件: 如onclick this->發生事件的物件
建構函式
this->new 出來的object
call/apply
改變this
27. 你如何優化自己的程式碼?
程式碼重用
避免全域性變數(名稱空間,封閉空間,模組化mvc..)
拆分函式避免函式過於臃腫
註釋
28. 請儘可能詳盡的解釋AJAX的工作原理
1).建立ajax物件(XMLHttpRequest/ActiveXObject(Microsoft.XMLHttp))
2)判斷資料傳輸方式(GET/POST)
3)開啟連結 open()
4)傳送 send()
5) 當ajax物件完成第四步(onreadystatechange)資料接收完成,判斷http響應狀態(status)200-300之間或者304(快取)執行回撥函式
29. 怎麼理解js中的事件委託
具體來說,事件委託就是事件目標自身不處理事件,而是把處理任務委託給其父元素或者祖先元素,甚至根元素(document)。jQuery為繫結和委託事件提供了.bind()、.live()和.delegate()方法
1..bind()只能給呼叫它的時候已經存在的元素繫結事件,不能給未來新增的元素繫結事件在下列情況下,應該使用.live()或.delegate(),而不能使用.bind():
2.為DOM中的很多元素繫結相同事件;
3.為DOM中尚不存在的元素繫結事件;
30. call 和 apply的含義和區別?
apply:方法能劫持另外一個物件的方法,繼承另外一個物件的屬性.
Function.apply(obj,args)方法能接收兩個引數
obj:這個物件將代替Function類裡this物件
args:這個是陣列,它將作為引數傳給Function(args-->arguments)
call:和apply的意思一樣,只不過是引數列表不一樣.
Function.call(obj,[param1[,param2[,…[,paramN]]]])
obj:這個物件將代替Function類裡this物件
params:這個是一個引數列表
在給物件引數的情況下,如果引數的形式是陣列的時候,比如apply示例裡面傳遞了引數arguments,這個引數是陣列型別,並且在呼叫Person的時候引數的列表是對應一致的(也就是Person和Student的引數列表前兩位是一致的) 就可以採用 apply , 如果我的Person的引數列表是這樣的(age,name),而Student的引數列表是(name,age,grade),這樣就可以用call來實現了,也就是直接指定引數列表對應值的位置(Person.call(this,age,name,grade));
apply的一些其他巧妙用法
呼叫apply方法的時候,第一個引數是物件(this), 第二個引數是一個陣列集合,在呼叫Person的時候,他需要的不是一個陣列,但是為什麼他給我一個陣列我仍然可以將陣列解析為一個一個的引數,
這個就是apply的一個巧妙的用處,可以將一個陣列預設的轉換為一個引數列表([param1,param2,param3] 轉換為 param1,param2,param3) 這個如果讓我們用程式來實現將陣列的每一個項,來裝換為引數的列表,可能都得費一會功夫,藉助apply的這點特性,所以就有了以下高效率的方法:
31. a、b、c分別輸出什麼?
function fun(n,o) {
console.log(o)
return {
fun:function(m){
return fun(m,n);
}
};
}
var a = fun(0);
a.fun(1);
a.fun(2);
a.fun(3);
var b = fun(0).fun(1).fun(2).fun(3);
var c = fun(0).fun(1); c.fun(2);
c.fun(3);
//undefined, 0, 0, 0
//undefined, 0, 1, 2
//undefined, 0, 1, 1複製程式碼
32. 看看下面這個會輸出什麼呢?
<ul id="test">
<li>這是第一條alert(0);</li>
<li>這是第二條alert(1);</li>
<li>這是第三條alert(2);</li>
</ul>
<script type="text/javascript">
var elements = document.getElementById('test').querySelectorAll('li');
for (var i = 0; i < elements.length; i++) {
elements[i].onclick = function () {
alert(i);
}
}
</script>//點選每一條都alert:2複製程式碼
33.讀程式給結果:
function A(){ }
function B(a){
this.a = a;
}
function C(a){
if(a){
this.a = a;
}
}
A.prototype.a = 1;
B.prototype.a = 1;
C.prototype.a = 1;
console.log(new A().a);
console.log(new B().a);
console.log(new C(2).a);
結果:
1、undefined、
2. 複製程式碼
34. 題目是
var F = function(){};
Object.prototype.a = function(){};
Function.prototype.b = function(){};
var f = new F();複製程式碼
問:呼叫f.a( )和f.b( ) 能成功麼?
答案:能呼叫f.a( )但是不能呼叫f.b( );
35. 有一條可愛的小狗(名字叫“小狗狗”),它的叫聲很好聽(wow),每次看到主人的時候就會乖乖叫(yelp)。另一隻小狗精力很旺盛(名字叫做“精力旺盛的狗狗”),每隔5秒叫喚(yelp)一聲(wow)。
使用物件導向的混合模式實現小狗的建立
function Dog() {
this.name = '小狗狗';
this.wow = 'wow';
}
Dog.prototype.yelp = function() {
console.log(this.wow);
}
function MadDog() {
Dog.call(this);
this.name = '精力旺盛的狗狗';
}
for (var i in Dog.prototype) {
MadDog.prototype[i] = Dog.prototype[i];
};
MadDog.prototype.yelp = function () {
var _this = this;
setInterval(function(){
console.log(_this.wow);
}, 5000);
}
var dog = new MadDog();
dog.yelp();複製程式碼
36. HTTP狀態碼知道哪些?
100 Continue繼續,一般在傳送post請求時,已傳送了http header之後服務端將返回此資訊,表示確認,之後傳送具體引數資訊
200 OK 正常返回資訊
201 Created請求成功並且伺服器建立了新的資源
202 Accepted伺服器已接受請求,但尚未處理
301 Moved Permanently請求的網頁已永久移動到新位置。
302 Found 臨時性重定向。
303 See Other臨時性重定向,且總是使用 GET 請求新的 URI。
304 Not Modified自從上次請求後,請求的網頁未修改過。
400 Bad Request伺服器無法理解請求的格式,客戶端不應當嘗試再次使用相同的內容發起請求。
401 Unauthorized 請求未授權。
403 Forbidden 禁止訪問。
404 Not Found 找不到如何與URI 相匹配的資源。
500 Internal ServerError 最常見的伺服器端錯誤。
503 Service Unavailable伺服器端暫時無法處理請求(可能是過載或維護)。
37. 你有哪些效能優化的方法?
(1) 減少http請求次數:CSSSprites, JS、CSS原始碼壓縮、圖片大小控制合適;網頁Gzip,CDN託管,data快取 ,圖片伺服器。
(2) 前端模板JS+資料,減少由於HTML標籤導致的頻寬浪費,前端用變數儲存ajax請求結果,每次操作本地變數,不用請求,減少請求次數
(3)用innerHTML代替DOM操作,減少DOM操作次數,優化javascript效能。
(4)當需要設定的樣式很多時設定className而不是直接操作style。
(5)少用全域性變數、快取DOM節點查詢的結果。減少IO讀取操作。
(6) 避免使用CSSExpression(css表示式)又稱Dynamic properties(動態屬性)。
(7)圖片預載入,將樣式表放在頂部,將指令碼放在底部 加上時間戳。
38. 哪些常見操作會造成記憶體洩漏?
記憶體洩漏指任何物件在您不再擁有或需要它之後仍然存在。
垃圾回收器定期掃描物件,並計算引用了每個物件的其他物件的數量。如果一個物件的引用數量為0(沒有其他物件引用過該物件),或對該物件的惟一引用是迴圈的,那麼該物件的記憶體即可回收。
setTimeout的第一個引數使用字串而非函式的話,會引發記憶體洩漏。
閉包、控制檯日誌、迴圈(在兩個物件彼此引用且彼此保留時,就會產生一個迴圈)。
39. 讀程式:
(function() {
var a = b = 5;
})();
console.log(b);
答案:5複製程式碼
40. 執行這段程式碼,輸出什麼結果。
function test() {
console.log(a);
console.log(foo());
var a = 1;
function foo() {
return 2;
}
}
test();複製程式碼
這段程式碼的結果是 undefined 和 2。
41. 下面的程式碼會輸出什麼結果?給出你的答案。
var fullname = 'John Doe';
var obj = {
fullname: 'Colin Ihrig',
prop: {
fullname: 'Aurelio De Rosa',
getFullname: function() {
return this.fullname;
}
}
};
console.log(obj.prop.getFullname());
var test = obj.prop.getFullname;
console.log(test());
答案是Aurelio De Rosa和John Doe。複製程式碼
42. 如何阻止事件冒泡和預設事件
e. stopPropagation();//標準瀏覽器阻止事件冒泡
event.canceBubble=true;//ie9之前阻止預設事件:為了不讓a點選之後跳轉,我們就要給他的點選事件進行阻止return
falsee.preventDefault();複製程式碼
43. new操作符具體幹了什麼呢?
1、建立一個空物件,並且 this 變數引用該物件,同時還繼承了該函式的原型。
2、屬性和方法被加入到 this 引用的物件中。
3、新建立的物件由 this 所引用,並且最後隱式的返回 this 。
jQuery:
1.說說你對延遲物件deferred的理解?
deferred物件是從jQuery 1.5.0版本開始引入的一個新功能。
a、什麼是deferred物件
開發網站的過程中,我們經常遇到某些耗時很長的javascript操作。其中,既有非同步的操作(比如ajax讀取伺服器資料),也有同步的操作(比如遍歷一個大型陣列),它們都不是立即能得到結果的。
通常的做法是,為它們指定回撥函式(callback)。即事先規定,一旦它們執行結束,應該呼叫哪些函式。
但是,在回撥函式方面,jQuery的功能非常弱。為了改變這一點,jQuery開發團隊就設計了deferred物件。
簡單說,deferred物件就是jQuery的回撥函式解決方案。在英語中,defer的意思是"延遲",所以deferred物件的含義就是"延遲"到未來某個點再執行。
它解決了如何處理耗時操作的問題,對那些操作提供了更好的控制,以及統一的程式設計介面。
b、它的主要功能,可以歸結為四點:
(1)、實現鏈式操作
(2)、指定同一操作的多個回撥函式
(3)、為多個操作指定回撥函式
(4)、普通操作的回撥函式介面
2. $.extend與$.fn.extend區別是什麼?
$.extend
在jQuery根名稱空間下直接呼叫的方法可以認為是jQuery的靜態方法或屬性,常常使用方法名來呼叫,使用.方法名來呼叫,使用.extend這個靜態方法可以完成兩個功能:
a、擴充套件屬性或方法給jQuery
b、擴充套件物件
$.fn.extend
.fn就是jQuery的原型,.fn等於jQuery.prototype,是jQuery的別名。.fn.extend方法的作用是用於擴充套件jQuery例項物件,也就是我們從頁面中獲得的jQuery物件。
.fn擴充套件了jQuery的原型,讓所有的jQuery例項物件都得到的擴充套件的方法,其它也可以直接修改jQuery.prototype來實現,.fn是jQuery.prototype的簡寫
3. 什麼是鏈式程式設計?
幾乎在所有基於“型別”的語言中如果呼叫一個方法後將物件作為方法引數返回則就會形成鏈式程式設計鏈式程式設計是將多個操作(多行程式碼)通過點號"."連結在一起成為一句程式碼。 鏈式程式碼通常要求操作有返回值, 但對於很多操作大都是void型,什麼也不返回,這樣就很難鏈起來了, 當然也有解決辦法,可能不太優雅。 鏈式程式設計的新思想在jQuery中已流行使用
示例:
return $.each(this,function(index, obj) {
$("<span/>").html("+").css("cursor","pointer").click(function() {
$(obj).width($(obj).width()+ length);
}).insertAfter(obj);
});複製程式碼
上面的示例中當$.each迴圈完成後返回this物件,返回的仍然是一個jQuery物件,所以可以繼續jQuery程式設計。
$("button").SuperPlus(10).height(26).width(100).css("color","blue");複製程式碼
4.window.load 和 document ready 的區別。
window.load 是整個文件結構和資源都載入完成執行此事件
documen ready 是整個文件結構載入完成即可執行
5. Jquery的美元符號$有什麼作用?
回答:其實美元符號$只是”jQuery”的別名,它是jQuery的選擇器,如下程式碼:
// aaa(a);
$(document).ready(function(){
/.../
});複製程式碼
當然你也可以用jQuery來代替$,如下程式碼:
jQuery(document).ready(function(){
/.../
});複製程式碼
jQuery中就是通過這個美元符號來實現各種靈活的DOM元素選擇的,例如$(“#main”)即選中id為main的元素。
6. Jquery中有哪幾種型別的選擇器?
從我自己的角度來講,可以有3種型別的選擇器,如下:
1、基本選擇器:直接根據id、css類名、元素名返回匹配的dom元素。
2、層次選擇器:也叫做路徑選擇器,可以根據路徑層次來選擇相應的DOM元素。
3、過濾選擇器:在前面的基礎上過濾相關條件,得到匹配的dom元素。
4、請使用jQuery將頁面上的所有元素邊框設定為2px寬的虛線?
程式碼如下:
<script language="javascript" type="text/javascript">
$("*").css("border", "2px dotted red");
</script>複製程式碼