前端面試題 | JS部分(附帶答案)

梭梭醬加油鴨發表於2019-04-11

目前在找工作,所以各方收集了一堆面試題。其實刷面試題的過程也能更新自己對知識的認識,所以也提醒自己多看多理解。如果對下面題目有更深理解,會實時更新。遇到新題目,也會不定時更新。希望能幫助到部分朋友~

一、各種函式方法定義及區別

1. typeof運算子和instanceof運算子以及isPrototypeOf()方法的區別

typeof是一個運算子,用於檢測資料的型別,比如基本資料型別null、undefined、string、number、boolean,以及引用資料型別object、function,但是對於正規表示式、日期、陣列這些引用資料型別,它會全部識別為object; instanceof同樣也是一個運算子,它就能很好識別資料具體是哪一種引用型別。它與isPrototypeOf的區別就是它是用來檢測建構函式的原型是否存在於指定物件的原型鏈當中;而isPrototypeOf是用來檢測呼叫此方法的物件是否存在於指定物件的原型鏈中,所以本質上就是檢測目標不同。

2.call()和apply()的區別

實際上,apply和call的功能是一樣的,只是傳入的引數列表形式不同。apply:最多隻能有兩個引數——新this物件和一個陣列argArray。

參考:www.cnblogs.com/lengyuehuah…

3.全域性函式eval()有什麼作用?

eval()只有一個引數,如果傳入的引數不是字串,它直接返回這個引數。如果引數是字串,它會把字串當成javascript程式碼進行編譯。如果編譯失敗則丟擲一個語法錯誤(syntaxError)異常。如果編譯成功,則開始執行這段程式碼,並返回字串中的最後一個表示式或語句的值,如果最後一個表示式或語句沒有值,則最終返回undefined。如果字串丟擲一個異常,這個異常將把該呼叫傳遞給eval()。

4.描述以下變數的區別:null,undefined或undeclared

null 表示"沒有物件",即該處不應該有值,轉為數值時為0。典型用法是:

(1) 作為函式的引數,表示該函式的引數不是物件。

(2) 作為物件原型鏈的終點。

undefined 表示"缺少值",就是此處應該有一個值,但是還沒有定義,轉為數值時為NaN。典型用法是:

(1)變數被宣告瞭,但沒有賦值時,就等於undefined。

(2) 呼叫函式時,應該提供的引數沒有提供,該引數等於undefined。

(3)物件沒有賦值的屬性,該屬性的值為undefined。

(4)函式沒有返回值時,預設返回undefined。

undeclared :js語法錯誤,沒有申明直接使用,js無法找到對應的上下文。

5.==和===有什麼區別?

首先,== equality 等同,=== identity 恆等。==,兩邊值型別不同的時候,要先進行型別轉換,再比較。===,不做型別轉換,型別不同的一定不等。

先說 ===,這個比較簡單。下面的規則用來判斷兩個值是否===相等:

如果型別不同,就[不相等] 
如果兩個都是數值,並且是同一個值,那麼[相等];(!例外)的是,如果其中至少一個是NaN,那麼[不相等]。(判斷一個值是否是NaN,只能用isNaN()來判斷) 
如果兩個都是字串,每個位置的字元都一樣,那麼[相等];否則[不相等]。 
如果兩個值都是true,或者都是false,那麼[相等]。 
如果兩個值都引用同一個物件或函式,那麼[相等];否則[不相等]。 
如果兩個值都是null,或者都是undefined,那麼[相等]。 
複製程式碼

再說 ==,根據以下規則: 如果兩個值型別相同,進行 === 比較。 如果兩個值型別不同,他們可能相等。根據下面規則進行型別轉換再比較:

如果一個是null、一個是undefined,那麼[相等]。 
如果一個是字串,一個是數值,把字串轉換成數值再進行比較。 
如果任一值是 true,把它轉換成 1 再比較;如果任一值是 false,把它轉換成 0 再比較。 
如果一個是物件,另一個是數值或字串,把物件轉換成基礎型別的值再比較。物件轉換成基礎型別,利用它的
toString或者valueOf方法。js核心內建類,會嘗試valueOf先於toString;例外的是Date,Date利用的是toString轉換。非js核心的物件,令說(比較麻煩,我也不大懂) 
任何其他組合,都[不相等]。
複製程式碼

6.同步非同步?

1、程式同步:就是在發出一個功能呼叫時,在沒有得到結果之前,該呼叫就不返回。也就是必須一件一件事做,等前一件做完了才能做下一件事 2、非同步的概念和同步相對。當一個非同步過程呼叫發出後,呼叫者不能立刻得到結果。實際處理這個呼叫的部件在完成後,通過狀態、通知和回撥來通知呼叫者。

二、各種概念/原理

1. 什麼是事件代理/事件委託?

事件代理/事件委託是利用事件冒泡的特性,將本應該繫結在多個元素上的事件繫結在他們的祖先元素上,尤其在動態新增子元素的時候,可以非常方便的提高程式效能,減小記憶體空間。

2.什麼是事件冒泡?什麼是事件捕獲?

冒泡型事件:事件按照從最特定的事件目標到最不特定的事件目標(document物件)的順序觸發。

捕獲型事件:事件從最不精確的物件(document 物件)開始觸發,然後到最精確(也可以在視窗級別捕獲事件,不過必須由開發人員特別指定)。

支援W3C標準的瀏覽器在新增事件時用addEventListener(event,fn,useCapture)方法,基中第3個引數useCapture是一個Boolean值,用來設定事件是在事件捕獲時執行,還是事件冒泡時執行。而不相容W3C的瀏覽器(IE)用attachEvent()方法,此方法沒有相關設定,不過IE的事件模型預設是在事件冒泡時執行的,也就是在useCapture等於false的時候執行,所以把在處理事件時把useCapture設定為false是比較安全,也實現相容瀏覽器的效果。

3.如何阻止冒泡?

w3c的方法是e.stopPropagation(),IE則是使用e.cancelBubble = true。例如: window.event? window.event.cancelBubble = true : e.stopPropagation();

return false也可以阻止冒泡。

4.如何阻止預設事件?

w3c的方法是e.preventDefault(),IE則是使用e.returnValue = false,比如:

function stopDefault( e ) { 
    //阻止預設瀏覽器動作(W3C) 
    if ( e && e.preventDefault ) 
        e.preventDefault(); 
    //IE中阻止函式器預設動作的方式 
    else 
        window.event.returnValue = false; 
}
複製程式碼

return false也能阻止預設行為。

5.簡述javascript中this的指向

第一準則是:this永遠指向函式執行時所在的物件,而不是函式被建立時所在的物件。

  • 普通的函式呼叫,函式被誰呼叫,this就是誰。
  • 建構函式的話,如果不用new操作符而直接呼叫,那即this指向window。用new操作符生成物件例項後,this就指向了新生成的物件。
  • 匿名函式或不處於任何物件中的函式指向window 。
  • 如果是call,apply等,指定的this是誰,就是誰。
  • 參考:www.cnblogs.com/beidan/p/53…

5.原生物件和宿主物件

原生物件是ECMAScript規定的物件,所有內建物件都是原生物件,比如Array、Date、RegExp等;

宿主物件是宿主環境比如瀏覽器規定的物件,用於完善是ECMAScript的執行環境,比如Document、Location、Navigator等。

6.基本資料型別和引用資料型別

基本資料型別指的是簡單的資料段,有5種,包括null、undefined、string、boolean、number;

引用資料型別指的是有多個值構成的物件,包括object、array、date、regexp、function等。

主要區別:

  • 宣告變數時不同的記憶體分配:前者由於佔據的空間大小固定且較小,會被儲存在棧當中,也就是變數訪問的位置;後者則儲存在堆當中,變數訪問的其實是一個指標,它指向儲存物件的記憶體地址。
  • 也正是因為記憶體分配不同,在複製變數時也不一樣。前者複製後2個變數是獨立的,因為是把值拷貝了一份;後者則是複製了一個指標,2個變數指向的值是該指標所指向的內容,一旦一方修改,另一方也會受到影響。
  • 引數傳遞不同:雖然函式的引數都是按值傳遞的,但是引用值傳遞的值是一個記憶體地址,實參和形參指向的是同一個物件,所以函式內部對這個引數的修改會體現在外部。原始值只是把變數裡的值傳遞給引數,之後引數和這個變數互不影響。

7.深拷貝和淺拷貝

區別 www.cnblogs.com/echolun/p/7…

深拷貝的方法 www.cnblogs.com/Mrrabbit/p/…

8.解釋一下原型繼承的原理

參考:www.cnblogs.com/syfwhu/p/44…

9.解釋下為什麼接下來這段程式碼不是IIFE(立即呼叫的函式表示式):

function foo(){
    //code
}()
複製程式碼

以function關鍵字開頭的語句會被解析為函式宣告,而函式宣告是不允許直接執行的。 只有當解析器把這句話解析為函式表示式,才能夠直接執行,怎麼辦呢?以運算子開頭就可以了。

(function foo(){
    // code..
})()
複製程式碼

10.請儘可能詳盡的解釋AJAX的工作原理

ajax簡單來說是通過XmlHttpRequest物件來向伺服器發非同步請求,從伺服器獲得資料,然後用javascript來操作DOM而更新頁面。

ajax的優點

  • 最大的一點是頁面無重新整理,在頁面內與伺服器通訊,給使用者的體驗非常好。
  • 使用非同步方式與伺服器通訊,不需要打斷使用者的操作,具有更加迅速的響應能力。
  • 可以把以前一些伺服器負擔的工作轉嫁到客戶端,利用客戶端閒置的能力來處理,減輕伺服器和頻寬的負擔,節約空間和寬頻租用成本,ajax的原則是“按需取資料”,可以最大程度的減少冗餘請求。
  • 基於標準化的並被廣泛支援的技術,不需要下載外掛或者小程式。

ajax的缺點

  • ajax對瀏覽器後退機制造成了破壞,也就是說使用者無法通過瀏覽器的後退按鈕回到前一次操作的頁面。雖然有些瀏覽器解決了這個問題,比如Gmail,但它也並不能改變ajax的機制,它所帶來的開發成本是非常高的,和ajax框架所要求的快速開發是相背離的。這是ajax所帶來的一個非常嚴重的問題。
  • 安全問題。技術同時也對IT企業帶來了新的安全威脅,ajax技術就如同對企業資料建立了一個直接通道。這使得開發者在不經意間會暴露比以前更多的資料和伺服器邏輯。
  • 對搜尋引擎的支援比較弱。
  • 破壞了程式的異常機制。至少從目前看來,像ajax.dll,ajaxpro.dll這些ajax框架是會破壞程式的異常機制的。關於這個問題,我曾經在開發過程中遇到過,但是查了一下網上幾乎沒有相關的介紹。後來我自己做了一次試驗,分別採用ajax和傳統的form提交的模式來刪除一條資料……給我們的除錯帶來了很大的困難。
  • 另外,像其他方面的一些問題,比如說違背了url和資源定位的初衷。例如,我給你一個url地址,如果採用了ajax技術,也許你在該url地址下面看到的和我在這個url地址下看到的內容是不同的。這個和資源定位的初衷是相背離的。
  • 一些手持裝置(如手機、PDA等)現在還不能很好的支援ajax,比如說我們在手機的瀏覽器上開啟採用ajax技術的網站時,它目前是不支援的,當然,這個問題和我們沒太多關係。

11.get和post有什麼區別?

其實,GET和POST本質上兩者沒有任何區別。他們都是HTTP協議中的請求方法。底層實現都是基於TCP/IP協議。所謂區別,只是瀏覽器廠家根據約定,做得限制而已。

  • get是通過明文傳送資料請求,而post是通過密文;
  • get傳輸的資料量有限,因為url的長度有限,post則不受限;
  • GET請求的引數只能是ASCII碼,所以中文需要URL編碼,而POST請求傳參沒有這個限制
  • GET產生一個TCP資料包;POST產生兩個TCP資料包。對於GET方式的請求,瀏覽器會把http header和data一併傳送出去,伺服器響應200(返回資料);而對於POST,瀏覽器先傳送header,伺服器響應100 continue,瀏覽器再傳送data,伺服器響應200 ok(返回資料)。
  • 參考:www.cnblogs.com/logsharing/…

12.請解釋變數宣告提升

通過var宣告的變數會被提升至作用域的頂端。不僅僅是變數,函式宣告也一樣會被提升。當同一作用域內同時出現變數和函式宣告提升時,變數仍然在函式前面。 參考:www.cnblogs.com/guanhuachen…

13.請指出document.onload和document.ready兩個事件的區別

頁面載入完成有兩種事件,一是ready,表示文件結構已經載入完成(不包含圖片等非文字媒體檔案),二是onload,指示頁面包含圖片等檔案在內的所有元素都載入完成。

14.如何從瀏覽器的URL中獲取查詢字串引數?

getUrlParam : function(name){
        //baidu.com/product/list?keyword=XXX&page=1
        var reg     = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
        var result  = window.location.search.substr(1).match(reg);
        return result ? decodeURIComponent(result[2]) : null;
    }
複製程式碼

前端面試題 | JS部分(附帶答案)

  • 首先設定一個函式,給這個函式傳遞一個引數,也就是url的search部分的key值;
  • 設定一個正規表示式,以&開頭或沒有,中間是引數,後面以#或&結尾或沒有;
  • 通過window.location.search.substr(1).match()匹配,返回一個陣列
  • 如果陣列不為空,返回陣列的第3個值,也就是正規表示式的第二個子串

15.什麼是三元表示式?“三元”表示什麼意思?

三元表示式:? :。三元--三個操作物件。

在表示式boolean-exp ? value0 : value1 中,如果“布林表示式”的結果為true,就計算“value0”,而且這個計算結果也就是操作符最終產生的值。如果“布林表示式”的結果為false,就計算“value1”,同樣,它的結果也就成為了操作符最終產生的值。

16.JavaScript裡arguments究竟是什麼?

Javascrip中國每個函式都會有一個Arguments物件例項arguments,它引用著函式的實參,可以用陣列下標的方式"[]"引用arguments的元素。arguments.length為函式實參個數,arguments.callee引用函式自身。

在函式程式碼中,使用特殊物件arguments,開發者無需明確指出引數名,通過使用下標就可以訪問相應的引數。

function test() {
        var s = "";
        for (var i = 0; i < arguments.length; i++) {
            alert(arguments[i]);
            s += arguments[i] + ",";
        }
        return s;
    }
    test("name", "age");//name,age
複製程式碼

arguments雖然有一些陣列的性質,但其並非真正的陣列,只是一個類陣列物件。其並沒有陣列的很多方法,不能像真正的陣列那樣呼叫.jion(),.concat(),.pop()等方法。

17.什麼是"use strict";?使用它的好處和壞處分別是什麼?

在程式碼中出現表示式-"use strict"; 意味著程式碼按照嚴格模式解析,這種模式使得Javascript在更嚴格的條件下執行。

好處:

  • 消除Javascript語法的一些不合理、不嚴謹之處,減少一些怪異行為;
  • 消除程式碼執行的一些不安全之處,保證程式碼執行的安全;
  • 提高編譯器效率,增加執行速度;
  • 為未來新版本的Javascript做好鋪墊。

壞處:

  • 同樣的程式碼,在"嚴格模式"中,可能會有不一樣的執行結果;
  • 一些在"正常模式"下可以執行的語句,在"嚴格模式"下將不能執行。

18.請解釋一下JavaScript的同源策略

同源策略,即擁有相同的協議(protocol),埠(如果指定),主機(域名)的兩個頁面是屬於同一個源。 然而在IE中比較特殊,IE中沒有將埠號加入同源的條件中,因此上圖中埠不同那一項,在IE中是算同源的。 <script> <img> <iframe>中的src,href都可以任意連結網路資源,是不遵循通源策略的。

19.請解釋JSONP的工作原理,以及它為什麼不是真正的AJAX。

JSONP (JSON with Padding)是一個簡單高效的跨域方式,HTML中的script標籤可以載入並執行其他域的javascript,於是我們可以通過script標記來動態載入其他域的資源。例如我要從域A的頁面pageA載入域B的資料,那麼在域B的頁面pageB中我以JavaScript的形式宣告pageA需要的資料,然後在 pageA中用script標籤把pageB載入進來,那麼pageB中的指令碼就會得以執行。JSONP在此基礎上加入了回撥函式,pageB載入完之後會執行pageA中定義的函式,所需要的資料會以引數的形式傳遞給該函式。JSONP易於實現,但是也會存在一些安全隱患,如果第三方的指令碼隨意地執行,那麼它就可以篡改頁面內容,截獲敏感資料。但是在受信任的雙方傳遞資料,JSONP是非常合適的選擇。

AJAX是不跨域的,而JSONP是一個是跨域的,還有就是二者接收引數形式不一樣!

20.通過new建立一個物件的時候,建構函式內部有哪些改變?

function Person(){}
Person.prototype.friend = [];
Person.prototype.name = '';
var a = new Person();
a.friend[0] = '王琦';
var b = new Person();
console.log(b.friend);//Array [ "王琦" ]
複製程式碼
  • 建立一個空物件,並且 this 變數引用該物件,同時還繼承了該函式的原型。
  • 屬性和方法被加入到 this 引用的物件中。
  • 新建立的物件由 this 所引用,並且最後隱式的返回 this 。

22.什麼是跨域?有什麼方法解決跨域帶來的問題?

跨域需要針對瀏覽器的同源策略來理解,同源策略指的是請求必須是同一個埠,同一個協議,同一個域名,不同源的客戶端指令碼在沒有明確授權的情況下,不能讀寫對方資源。

受瀏覽器同源策略的影響,不是同源的指令碼不能操作其他源下面的物件。想要操作另一個源下的物件是就需要跨域。

解決方法: jsonp

未完待續……

相關文章