前端基礎面試題(JS部分)
1.幾種基本數據類型?複雜數據類型?值類型和引用數據類型?堆棧數據結構?javascript
基本數據類型:Undefined、Null、Boolean、Number、String
值類型:數值、布爾值、null、undefined。
引用類型:對象、數組、函數。
堆棧數據結構:是一種支持後進先出(LIFO)的集合,即後被插入的數據,先被取出!
js數組中提供瞭如下幾個方法可讓咱們很方便實現堆棧:
shift:從數組中把第一個元素刪除,並返回這個元素的值。
unshift: 在數組的開頭添加一個或更多元素,並返回新的長度
push:在數組的中末尾添加元素,並返回新的長度
pop:從數組中把最後一個元素刪除,並返回這個元素的值。php
2.聲明函數做用提高?聲明變量和聲明函數的提高有什麼區別?css
(1) 變量聲明提高:變量申明在進入執行上下文就完成了。
只要變量在代碼中進行了聲明,不管它在哪一個位置上進行聲明, js引擎都會將它的聲明放在範圍做用域的頂部;html(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);java
3.判斷數據類型?node
typeof返回的類型都是字符串形式,能夠判斷function的類型;在判斷除Object類型的對象時比較方便。
判斷已知對象類型的方法: instanceof,後面必定要是對象類型,而且大小寫不能錯,該方法適合一些條件選擇或分支。jquery
4.異步編程?webpack
方法1:回調函數,優勢是簡單、容易理解和部署,缺點是不利於代碼的閱讀和維護,各個部分之間高度耦合(Coupling),流程會很混亂,並且每一個任務只能指定一個回調函數。git
方法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 的第一個參數使用字符串而非函數的話,會引起內存泄漏。
閉包、控制檯日誌、循環(在兩個對象彼此引用且彼此保留時,就會產生一個循環)
防止內存泄露:
一、不要動態綁定事件;
二、不要在動態添加,或者會被動態移除的dom上綁事件,用事件冒泡在父容器監聽事件;
三、若是要違反上面的原則,必須提供destroy方法,保證移除dom後事件也被移除,這點能夠參考Backbone的源代碼,作的比較好;
四、單例化,少建立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.自執行函數?用於什麼場景?好處?
自執行函數:一、聲明一個匿名函數二、立刻調用這個匿名函數。
做用:建立一個獨立的做用域。好處:防止變量彌散到全局,以避免各類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?
一、建立一個空對象,而且 this 變量引用該對象,同時還繼承了該函數的原型。
二、屬性和方法被加入到 this 引用的對象中。
三、新建立的對象由 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.強制轉換 顯式轉換 隱式轉換?
//強制類型轉換: Boolean(0) // => false - 零 Boolean(new object()) // => true - 對象 Number(undefined) // => NaN Number(null) // => 0 String(null) // => "null" parseInt( ) parseFloat( ) JSON.parse( ) JSON.stringify ( )
隱式類型轉換:
在使用算術運算符時,運算符兩邊的數據類型能夠是任意的,好比,一個字符串能夠和數字相加。之因此不一樣的數據類型之間能夠作運算,是由於JavaScript引擎在運算以前會悄悄的把他們進行了隱式類型轉換的
(例如:x+"" //等價於String(x)
+x //等價於Number(x)
x-0 //同上
!!x //等價於Boolean(x),是雙歎號)顯式轉換:
若是程序要求必定要將某一類型的數據轉換爲另外一種類型,則能夠利用強制類型轉換運算符進行轉換,這種強制轉換過程稱爲顯示轉換。
顯示轉換是你定義讓這個值類型轉換成你要用的值類型,是底到高的轉換。例 int 到float就能夠直接轉,int i=5,想把他轉換成char類型,就用顯式轉換(char)i
22. Jq中如何實現多庫並存?
Noconfict 多庫共存就是「$ 」符號的衝突。
方法一: 利用jQuery的實用函數.noConflict();這個函數歸還.noConflict();這個函數歸還的名稱控制權給另外一個庫,所以能夠在頁面上使用其餘庫。這時,咱們能夠用"jQuery "這個名稱調用jQuery的功能。 .noConflict();
jQuery('#id').hide();
.....
//或者給jQuery一個別名
var.noConflict(); jQuery('#id').hide(); ..... //或者給jQuery一個別名 varj=jQuery
$j('#id').hide();
.....方法二: (function($){})(jQuery)
方法三: jQuery(function())通過傳遞一個函數做爲jQuery的參數,因此把這個函數聲明爲就緒函數。我們聲明))經過傳遞一個函數做爲jQuery的參數,所以把這個函數聲明爲就緒函數。咱們聲明爲就緒函數的參數,由於jQuery老是吧jQuery對象的引用做爲第一個參數傳遞,因此就保證了函數的執行。
23.Jq中get和eq有什麼區別?
get() :取得其中一個匹配的元素。num表示取得第幾個匹配的元素,get多針對集合元素,返回的是DOM對象組成的數組 eq():獲取第N個元素,下標都是從0開始,返回的是一個JQuery對象
24.如何經過原生js 判斷一個元素當前是顯示仍是隱藏狀態?
if( document.getElementById("div").css("display")==='none') if( document.getElementById("div").css("display")==='block') $("#div").is(":hidden"); // 判斷是否隱藏 $("#div").is(":visible")
25.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(); }
26.移動端上什麼是點擊穿透?
點擊穿透現象有3種:
點擊穿透問題:點擊蒙層(mask)上的關閉按鈕,蒙層消失後發現觸發了按鈕下面元素的click事件跨頁面點擊穿透問題:若是按鈕下面剛好是一個有href屬性的a標籤,那麼頁面就會發生跳轉另外一種跨頁面點擊穿透問題:此次沒有mask了,直接點擊頁內按鈕跳轉至新頁,而後發現新頁面中對應位置元素的click事件被觸發了解決方案:
一、只用touch
最簡單的解決方案,完美解決點擊穿透問題
把頁面內全部click所有換成touch事件( touchstart 、’touchend’、’tap’)二、只用click
下下策,由於會帶來300ms延遲,頁面內任何一個自定義交互都將增長300毫秒延遲三、tap後延遲350ms再隱藏mask
改動最小,缺點是隱藏mask變慢了,350ms仍是能感受到慢的四、pointer-events
比較麻煩且有缺陷, 不建議使用mask隱藏後,給按鈕下面元素添上 pointer-events: none; 樣式,讓click穿過去,350ms後去掉這個樣式,恢復響應缺陷是mask消失後的的350ms內,用戶能夠看到按鈕下面的元素點着沒反應,若是用戶手速很快的話必定會發現
27.Jq綁定事件的幾種方式?on bind ?
jQuery中提供了四種事件監聽方式,分別是bind、live、delegate、on,對應的解除監聽的函數分別是unbind、die、undelegate、off
Bind( )是使用頻率較高的一種,做用就是在選擇到的元素上綁定特定事件類型的監聽函數;
Live( )能夠對後生成的元素也能夠綁定相應的事件,處理機制就是把事件綁定在DOM樹的根節點上,而不是直接綁定在某個元素上;
Delegate( )採用了事件委託的概念,不是直接爲子元素綁定事件,而是爲其父元素(或祖先元素也可)綁定事件,當在div內任意元素上點擊時,事件會一層層從event target向上冒泡,直至到達你爲其綁定事件的元素;
on( )方法能夠綁定動態添加到頁面元素的事件,on()方法綁定事件能夠提高效率;
28.Jq中如何將一個jq對象轉化爲dom對象?
方法一:
jQuery對象是一個數據對象,能夠經過[index]的方法,來獲得相應的DOM對象。
如:var v=v=("#v") ; //jQuery對象
var v=$v[0]; //DOM對象
alert(v.checked) //檢測這個checkbox是否被選中方法二:
jQuery自己提供,經過.get(index)方法,獲得相應的DOM對象
如:var v=v=("#v"); //jQuery對象
var v=$v.get(0); //DOM對象
alert(v.checked) //檢測這個checkbox是否被選中
29.Jq中有幾種選擇器?分別是什麼?
層疊選擇器、基本過濾選擇器、內容過濾選擇器、可視化過濾選擇器、屬性過濾選擇器、子元素過濾選擇器、表單元素選擇器、表單元素過濾選擇器
30.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); //形參是$,函數定義完成以後,把jQuery這個實參傳遞進去.當即調用執行。 //這樣的好處是,咱們在寫jQuery插件時,也可使用$這個別名,而不會與prototype引發衝突
31.(′div+.ab′)和(′div+.ab′)和('.ab+div') 哪一個效率高?
$('div+.ab')效率高
32..map和.map和.each有什麼區別
map()方法主要用來遍歷操做數組和對象,會返回一個新的數組。$.map()方法適用於將數組或對象每一個項目新陣列映射到一個新數組的函數;
each()主要用於遍歷jquery對象,返回的是原來的數組,並不會新建立一個數組。
33.編寫一個 getElementsByClassName 封裝函數?
<body> <input type="submit" id = "sub" class="ss confirm btn" value="提交"/> <script> window.onload = function(){ //方法一 var Opt = document.getElementById('sub'); var getClass = function(className,tagName){ if(document.getElementsByTagName){ var Inp = document.getElementsByTagName(tagName); for(var i=0; i<Inp.length; i++){ if((new RegExp('(\\s|^)' +className +'(\\s|$)')).test(Inp[i].className)){ return Inp[i]; } } }else if(document.getElementsByClassName){ return document.getElementsByClassName(className); } } //方法二 var aa = getClass("confirm", "input"); function getClass(className, targetName){ var ele = []; var all = document.getElementsByTagName(targetName || "*"); for(var i=0; i<all.length; i++){ if(all[i].className.match(new RegExp('(\\s|^)'+confirm+'(\\s|$)'))){ ele[ele.length] = all[i]; } } return ele; } //方法三 function getObjsByClass(tagName, className){ if(document.getElementsByClassName){ alert("document.getElementsByClassName"); return document.getElementsByClassName(className); }else{ var el = []; var _el = document.getElementsByTagName(tagName);