前端基礎面試題大全-極樂科技(一)-JS部分
JS部分
1.幾種基本資料型別?複雜資料型別?值型別和引用資料型別?堆疊資料結構?
基本資料型別:Undefined、Null、Boolean、Number、String
值型別:數值、布林值、null、undefined。
引用型別:物件、陣列、函式。
堆疊資料結構:是一種支援後進先出(LIFO)的集合,即後被插入的資料,先被取出!
js陣列中提供了以下幾個方法可以讓我們很方便實現堆疊:
shift:從陣列中把第一個元素刪除,並返回這個元素的值。
unshift: 在陣列的開頭新增一個或更多元素,並返回新的長度
push:在陣列的中末尾新增元素,並返回新的長度
pop:從陣列中把最後一個元素刪除,並返回這個元素的值。
2.宣告函式作用提升?宣告變數和宣告函式的提升有什麼區別?
(1)變數宣告提升:變數申明在進入執行上下文就完成了。
只要變數在程式碼中進行了宣告,無論它在哪個位置上進行宣告, js引擎都會將它的宣告放在範圍作用域的頂部;
(2)函式宣告提升:執行程式碼之前會先讀取函式宣告,意味著可以把函式申明放在呼叫它的語句後面。
只要函式在程式碼中進行了宣告,無論它在哪個位置上進行宣告, js引擎都會將它的宣告放在範圍作用域的頂部;
(3)變數or函式宣告:函式宣告會覆蓋變數宣告,但不會覆蓋變數賦值。
同一個名稱標識a,即有變數宣告var a,又有函式宣告function a() {},不管二者宣告的順序,函式宣告會覆蓋變數宣告,也就是說,此時a的值是宣告的函式function a() {}。注意:如果在變數宣告的同時初始化a,或是之後對a進行賦值,此時a的值變數的值。eg: var a; var c = 1; a = 1; function a() { return true; } console.log(a);
3.判斷資料型別?
typeof返回的型別都是字串形式,可以判斷function的型別;在判斷除Object型別的物件時比較方便。
判斷已知物件型別的方法: instanceof,後面一定要是物件型別,並且大小寫不能錯,該方法適合一些條件選擇或分支。
4.非同步程式設計?
方法1:回撥函式,優點是簡單、容易理解和部署,缺點是不利於程式碼的閱讀和維護,各個部分之間高度耦合(Coupling),流程會很混亂,而且每個任務只能指定一個回撥函式。
方法2:時間監聽,可以繫結多個事件,每個事件可以指定多個回撥函式,而且可以“去耦合”(Decoupling),有利於實現模組化。缺點是整個程式都要變成事件驅動型,執行流程會變得很不清晰。
方法3:釋出/訂閱,性質與“事件監聽”類似,但是明顯優於後者。
方法4:Promises物件,是CommonJS工作組提出的一種規範,目的是為非同步程式設計提供統一介面。
簡單說,它的思想是,每一個非同步任務返回一個Promise物件,該物件有一個then方法,允許指定回撥函式。
5.事件流?事件捕獲?事件冒泡?
事件流:從頁面中接收事件的順序。也就是說當一個事件產生時,這個事件的傳播過程,就是事件流。
IE中的事件流叫事件冒泡;事件冒泡:事件開始時由最具體的元素接收,然後逐級向上傳播到較為不具體的節點(文件)。對於html來說,就是當一個元素產生了一個事件,它會把這個事件傳遞給它的父元素,父元素接收到了之後,還要繼續傳遞給它的上一級元素,就這樣一直傳播到document物件(親測現在的瀏覽器到window物件,只有IE8及下不這樣);
事件捕獲是不太具體的元素應該更早接受到事件,而最具體的節點應該最後接收到事件。他們的用意是在事件到達目標之前就捕獲它;也就是跟冒泡的過程正好相反,以html的click事件為例,document物件(DOM級規範要求從document開始傳播,但是現在的瀏覽器是從window物件開始的)最先接收到click事件的然後事件沿著DOM樹依次向下傳播,一直傳播到事件的實際目標;
6.如何清除一個定時器?
window.clearInterval();
window.clearTimeout();
7.如何新增一個dom物件到body中?innerHTML和innerText區別?
body.appendChild(dom元素);
innerHTML:從物件的起始位置到終止位置的全部內容,包括Html標籤。
innerText:從起始位置到終止位置的內容, 但它去除Html標籤
分別簡述五個window物件、屬性
成員物件
window.event window.document window.history
window.screen window.navigator window.external
Window物件的屬性如下:
window //窗戶自身
window.self //引用本窗戶window=window.self
window.name //為窗戶命名
window.defaultStatus //設定窗戶狀態列資訊 window.location //URL地址,
配備佈置這個屬性可以開啟新的頁面
8.資料持久化技術(ajax)?簡述ajax流程
1)客戶端產生js的事件
2)建立XMLHttpRequest物件
3)對XMLHttpRequest進行配置
4)通過AJAX引擎傳送非同步請求
5)伺服器端接收請求並且處理請求,返回html或者xml內容
6)XML呼叫一個callback()處理響應回來的內容
7)頁面區域性重新整理
9.回撥函式?
回撥函式就是一個通過函式指標呼叫的函式。如果你把函式的指標(地址)作為引數傳遞給另一個函式,當這個指標被用來呼叫其所指向的函式時,我們就說這是回撥函式。回撥函式不是由該函式的實現方直接呼叫,而是在特定的事件或條件發生時由另外的一方呼叫的,用於對該事件或條件進行響應。
10.什麼是閉包?* 堆疊溢位有什麼區別? 記憶體洩漏? 那些操作會造成記憶體洩漏?怎麼樣防止記憶體洩漏?
閉包:就是能夠讀取其他函式內部變數的函式。
堆疊溢位:就是不顧堆疊中分配的區域性資料塊大小,向該資料塊寫入了過多的資料,導致資料越界,結果覆蓋了別的資料。經常會在遞迴中發生。
記憶體洩露是指:用動態儲存分配函式記憶體空間,在使用完畢後未釋放,導致一直佔據該記憶體單元。直到程式結束。指任何物件在您不再擁有或需要它之後仍然存在。
造成記憶體洩漏:
setTimeout 的第一個引數使用字串而非函式的話,會引發記憶體洩漏。
閉包、控制檯日誌、迴圈(在兩個物件彼此引用且彼此保留時,就會產生一個迴圈)
防止記憶體洩露:
1、不要動態繫結事件;
2、不要在動態新增,或者會被動態移除的dom上綁事件,用事件冒泡在父容器監聽事件;
3、如果要違反上面的原則,必須提供destroy方法,保證移除dom後事件也被移除,這點可以參考Backbone的原始碼,做的比較好;
4、單例化,少建立dom,少綁事件。
11.平時工作中怎麼樣進行資料互動?如果後臺沒有提供資料怎麼樣進行開發?mock資料與後臺返回的格式不同意怎麼辦?
由後臺編寫介面文件、提供資料介面實、前臺通過ajax訪問實現資料互動;
在沒有資料的情況下尋找後臺提供靜態資料或者自己定義mock資料;
返回資料不統一時編寫對映檔案 對資料進行對映。
12 簡述ajax執行流程
基本步驟:
var xhr =null;//建立物件
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
xhr.open(“方式”,”地址”,”標誌位”);//初始化請求
xhr.setRequestHeader(“”,””);//設定http頭資訊
xhr.onreadystatechange =function(){}//指定回撥函式
xhr.send();//傳送請求
13.自執行函式?用於什麼場景?好處
自執行函式:1、宣告一個匿名函式2、馬上呼叫這個匿名函式。
作用:建立一個獨立的作用域。
好處:防止變數彌散到全域性,以免各種js庫衝突。隔離作用域避免汙染,或者截斷作用域鏈,避免閉包造成引用變數無法釋放。利用立即執行特性,返回需要的業務函式或物件,避免每次通過條件判斷來處理
場景:一般用於框架、外掛等場景
14.html和xhtml有什麼區別?
HTML是一種基本的WEB網頁設計語言,XHTML是一個基於XML的標記語言。
1.XHTML 元素必須被正確地巢狀。2.XHTML 元素必須被關閉。3.標籤名必須用小寫字母。4.空標籤也必須被關閉。5.XHTML 文件必須擁有根元素。
15. 什麼是建構函式?與普通函式有什麼區別?
建構函式:是一種特殊的方法、主要用來建立物件時初始化物件,總與new運算子一起使用,建立物件的語句中建構函式的函式名必須與類名完全相同。
與普通函式相比只能由new關鍵字呼叫,建構函式是類的標示
16. 通過new建立一個物件的時候,函式內部有哪些改變
function Person(){}
Person.prototype.friend = [];
Person.prototype.name = '';
// var a = new Person();
// a.friend[0] = '王琦';
// a.name = '程嬌';
// var b = new Person();
// b.friend?
// b.name?
1、建立一個空物件,並且 this 變數引用該物件,同時還繼承了該函式的原型。
2、屬性和方法被加入到 this 引用的物件中。
3、新建立的物件由 this 所引用,並且最後隱式的返回 this 。
17.事件委託?有什麼好處?
答:(1)利用冒泡的原理,把事件加到父級上,觸發執行效果
(2)好處:新新增的元素還會有之前的事件;提高效能。
18.window.onload ==? DOMContentLoaded ?
答:一般情況下,DOMContentLoaded事件要在window.onload之前執行,當DOM樹構建完成的時候就會執行DOMContentLoaded事件,而window.onload是在頁面載入完成的時候,才執行,這其中包括圖片等元素。大多數時候我們只是想在DOM樹構建完成後,繫結事件到元素,我們並不需要圖片元素,加上有時候載入外域圖片的速度非常緩慢。
19.節點型別?判斷當前節點型別?
答:1 元素節點
2 屬性節點
3 文字節點
8 註釋節點
9 文件節點
通過nodeObject.nodeType判斷節點型別:其中,nodeObject 為DOM節點(節點物件)。該屬性返回以數字表示的節點型別,例如,元素節點返回 1,屬性節點返回 2 。
20.如何合併兩個陣列?陣列刪除一個元素?
答:三種方法。
(1)var arr1=[1,2,3];
var arr2=[4,5,6];
arr1 = arr1.concat(arr2);
console.log(arr1);
(2)var arr1=[1,2,3];
var arr2=[4,5,6];
Array.prototype.push.apply(arr1,arr2);
console.log(arr1);
(3)var arr1=[1,2,3];
var arr2=[4,5,6];
for (var i=0; i < arr2.length; i++) {
arr1.push( arr2[i] );
}
console.log(arr1);
21.強制轉換 顯式轉換 隱式轉換?
答:(1)強制型別轉換:
Boolean(0) // => false - 零
Boolean(new object()) // => true - 物件
Number(undefined) // => NaN
Number(null) // => 0
String(null) // => "null"
parseInt( )
parseFloat( )
JSON.parse( )
JSON.stringify ( )
(2)隱式型別轉換:
在使用算術運算子時,運算子兩邊的資料型別可以是任意的,比如,一個字串可以和數字相加。之所以不同的資料型別之間可以做運算,是因為JavaScript引擎在運算之前會悄悄的把他們進行了隱式型別轉換的
(例如:x+"" //等價於String(x)
+x //等價於Number(x)
x-0 //同上
!!x //等價於Boolean(x),是雙歎號)
(3)顯式轉換:
如果程式要求一定要將某一型別的資料轉換為另一種型別,則可以利用強制型別轉換運算子進行轉換,這種強制轉換過程稱為顯示轉換。
顯示轉換是你定義讓這個值型別轉換成你要用的值型別,是底到高的轉換。例 int 到float就可以直接轉,
int i=5,想把他轉換成char型別,就用顯式轉換(char)i
22. var a = true;
typeof a++ //number
typeof true++ //錯誤!
typeof a+1 //number1
typeof (true)+1 //boolean1
23.jq中如何實現多庫並存?Noconfict
多庫共存就是“
$.noConflict();
jQuery('#id').hide();
.....
//或者給jQuery一個別名
var $j=jQuery
$j('#id').hide();
.....
方法二:
(function($){
})(jQuery)
方法三:
jQuery(function($){
})
通過傳遞一個函式作為jQuery的引數,因此把這個函式宣告為就緒函式。
我們宣告$為就緒函式的引數,因為jQuery總是吧jQuery物件的引用作為第一個引數傳遞,所以就保證了函式的執行。
24.jq中 get 和 eq有什麼區別?
get() :取得其中一個匹配的元素。num表示取得第幾個匹配的元素,get多針對集合元素,返回的是DOM物件組成的陣列
eq():獲取第N個元素,下標都是從0開始,返回的是一個JQuery物件
25.如何通過原生js 判斷一個元素當前是顯示還是隱藏狀態?
if( document.getElementById("div").css("display")==='none')
if( document.getElementById("div").css("display")==='block')
$("#div").is(":hidden"); // 判斷是否隱藏
$("#div").is(":visible")
26.jq如何判斷元素顯示隱藏?
第一種:使用CSS屬性
var display =$('#id').css('display');
if(display == 'none'){
alert("我是隱藏的!");
}
第二種:使用jquery內建選擇器
<div id="test">
<p>僅僅是測試所用</p>
</div>
if($("#test").is(":hidden")){
$("#test").show(); //如果元素為隱藏,則將它顯現
}else{
$("#test").hide(); //如果元素為顯現,則將其隱藏
}
第三種:jQuery判斷元素是否顯示 是否隱藏
var node=$('#id');
if(node.is(':hidden')){ //如果node是隱藏的則顯示node元素,否則隱藏
node.show();
}else{
node.hide();
}
27.移動端上什麼是點選穿透?
點選穿透現象有3種:
點選穿透問題:點選蒙層(mask)上的關閉按鈕,蒙層消失後發現觸發了按鈕下面元素的click事件
跨頁面點選穿透問題:如果按鈕下面恰好是一個有href屬性的a標籤,那麼頁面就會發生跳轉
另一種跨頁面點選穿透問題:這次沒有mask了,直接點選頁內按鈕跳轉至新頁,然後發現新頁面中對應位置元素的click事件被觸發了
解決方案:
1、只用touch
最簡單的解決方案,完美解決點選穿透問題
把頁面內所有click全部換成touch事件( touchstart 、’touchend’、’tap’)
2、只用click
下下策,因為會帶來300ms延遲,頁面內任何一個自定義互動都將增加300毫秒延遲
3、tap後延遲350ms再隱藏mask
改動最小,缺點是隱藏mask變慢了,350ms還是能感覺到慢的
4、pointer-events
比較麻煩且有缺陷, 不建議使用
mask隱藏後,給按鈕下面元素添上 pointer-events: none; 樣式,讓click穿過去,350ms後去掉這個樣式,恢復響應
缺陷是mask消失後的的350ms內,使用者可以看到按鈕下面的元素點著沒反應,如果使用者手速很快的話一定會發現
28.jq繫結事件的幾種方式?on bind
jQuery中提供了四種事件監聽方式,分別是bind、live、delegate、on,對應的解除監聽的函式分別是unbind、die、undelegate、off
Bind( )是使用頻率較高的一種,作用就是在選擇到的元素上繫結特定事件型別的監聽函式;
Live( )可以對後生成的元素也可以繫結相應的事件,處理機制就是把事件繫結在DOM樹的根節點上,而不是直接繫結在某個元素上;
Delegate( )採用了事件委託的概念,不是直接為子元素繫結事件,而是為其父元素(或祖先元素也可)繫結事件,當在div內任意元素上點選時,事件會一層層從event target向上冒泡,直至到達你為其繫結事件的元素;
on( )方法可以繫結動態新增到頁面元素的事件,on()方法繫結事件可以提升效率;
29.jq中如何將一個jq物件轉化為dom物件?
方法一:
jQuery物件是一個數據物件,可以通過[index]的方法,來得到相應的DOM物件。
如:var
var v=
var v=v.get(0); //DOM物件
alert(v.checked) //檢測這個checkbox是否被選中
30.jq中有幾種選擇器?分別是什麼?
層疊選擇器、基本過濾選擇器、內容過濾選擇器、視覺化過濾選擇器、屬性過濾選擇器、子元素過濾選擇器、表單元素選擇器、表單元素過濾選擇器
31.jq中怎麼樣編寫外掛?
第一種是類級別的外掛開發:
1.1 新增一個新的全域性函式
新增一個全域性函式,我們只需如下定義:
jQuery.foo = function() {
alert('This is a test. This is only a test.');
};
1.2 增加多個全域性函式
新增多個全域性函式,可採用如下定義:
jQuery.foo = function() {
alert('This is a test. This is only a test.');
};
jQuery.bar = function(param) {
alert('This function takes a parameter, which is "' + param + '".');
};
呼叫時和一個函式的一樣的:jQuery.foo();jQuery.bar();或者$.foo();$.bar('bar');
1.3 使用jQuery.extend(object);
jQuery.extend({
foo: function() {
alert('This is a test. This is only a test.');
},
bar: function(param) {
alert('This function takes a parameter, which is "' + param +'".');
}
});
1.4 使用名稱空間
雖然在jQuery名稱空間中,我們禁止使用了大量的javaScript函式名和變數名。但是仍然不可避免某些函式或變數名將於其他jQuery外掛衝突,因此我們習慣將一些方法封裝到另一個自定義的名稱空間。
jQuery.myPlugin = {
foo:function() {
alert('This is a test. This is only a test.');
},
bar:function(param) {
alert('This function takes a parameter, which is "' + param + '".');
}
};
採用名稱空間的函式仍然是全域性函式,呼叫時採用的方法:
$.myPlugin.foo();
$.myPlugin.bar('baz');
通過這個技巧(使用獨立的外掛名),我們可以避免名稱空間內函式的衝突。
第二種是物件級別的外掛開發
形式1:
(function($){
$.fn.extend({
pluginName:function(opt,callback){
// Our plugin implementation code goes here.
}
})
})(jQuery);
形式2:
(function($) {
$.fn.pluginName = function() {
// Our plugin implementation code goes here.
};
})(jQuery);
形參是