1. 程式人生 > >前端面試JS題目複習大綱

前端面試JS題目複習大綱

前端面試JS題目

JS

介紹js的基本資料型別。

Undefined、Null、Boolean、Number、String、

複雜資料型別:Object

 

介紹js有哪些內建物件?

Object 是 JavaScript 中所有物件的父物件
資料封裝類物件:Object、Array、Boolean、Number 和 String
其他物件:Function、Arguments、Math、Date、RegExp、Error

 

說幾條寫JavaScript的基本規範?


1.不要在同一行宣告多個變數。

2.請使用 ===/!==

來比較true/false或者數值

3.使用物件字面量替代new Array這種形式

4.不要使用全域性函式。

5.Switch語句必須帶有default分支

6.函式不應該有時候有返回值,有時候沒有返回值。

7.For迴圈必須使用大括號

8.If語句必須使用大括號

9.for-in迴圈中的變數 應該使用var關鍵字明確限定作用域,從而避免作用域汙染。

 

JavaScript原型,原型鏈 ? 有什麼特點?

每個物件都會在其內部初始化一個屬性,就是prototype(原型),當我們訪問一個物件的屬性時,
如果這個物件內部不存在這個屬性,那麼他就會去prototype裡找這個屬性,這個prototype又會有自己的prototype,
於是就這樣一直找下去,也就是我們平時所說的原型鏈的概念。
關係:instance.constructor.prototype = instance.__proto__
 
特點:
JavaScript物件是通過引用來傳遞的,我們建立的每個新物件實體中並沒有一份屬於自己的原型副本。當我們修改原型時,與之相關的物件也會繼承這一改變。
 
 當我們需要一個屬性的時,Javascript引擎會先看當前物件中是否有這個屬性, 如果沒有的話,
 就會查詢他的Prototype物件是否有這個屬性,如此遞推下去,一直檢索到 Object 內建物件。
    function
Func(){}
    Func.prototype.name = "Sean";
    Func.prototype.getInfo = function() {
      return this.name;
    }
    var person = new Func();//現在可以參考var person = Object.create(oldObject);
    console.log(person.getInfo());//它擁有了Func的屬性和方法
    //"Sean"
    console.log(Func.prototype);
    // Func { name="Sean", getInfo=function()}

 

JavaScript有幾種型別的值?,你能畫一下他們的記憶體圖嗎?

棧:原始資料型別(Undefined,Null,Boolean,Number、String) 
堆:引用資料型別(物件、陣列和函式)
 
兩種型別的區別是:儲存位置不同;
原始資料型別直接儲存在棧(stack)中的簡單資料段,佔據空間小、大小固定,屬於被頻繁使用資料,所以放入棧中儲存;
引用資料型別儲存在堆(heap)中的物件,佔據空間大、大小不固定。如果儲存在棧中,將會影響程式執行的效能;引用資料型別在棧中儲存了指標,該指標指向堆中該實體的起始地址。當直譯器尋找引用值時,會首先檢索其在棧中的地址,取得地址後從堆中獲得實體
 

如何實現陣列的隨機排序?

方法一: 
```javascript 



  var arr = [1,2,3,4,5,6,7,8,9,10]; 
     function randSort1(arr){ 
        for(var i = 0,len = arr.length;i < len; i++ ){ 
            var rand = parseInt(Math.random()*len); 
            var temp = arr[rand]; 
            arr[rand] = arr[i]; 
            arr[i] = temp; 
        }
         return arr;
     }
     console.log(randSort1(arr));
 
```
方法二:
```javascript
        var arr = [1,2,3,4,5,6,7,8,9,10];
        function randSort2(arr){
            var mixedArray = [];
            while(arr.length > 0){
                var randomIndex = parseInt(Math.random()*arr.length);
                mixedArray.push(arr[randomIndex]);
                arr.splice(randomIndex, 1);
            }
            return mixedArray;
        }
        console.log(randSort2(arr));
 
```
方法三:
```javascript
        var arr = [1,2,3,4,5,6,7,8,9,10];
        arr.sort(function(){
            return Math.random() - 0.5;
        })
        console.log(arr);
```                         

 

 

 

Javascript如何實現繼承?

1、構造繼承
2、原型繼承
3、例項繼承
4、拷貝繼承
 
原型prototype機制或apply和call方法去實現較簡單,建議使用建構函式與原型混合方式。
```javascript
        function Parent(){
            this.name = 'wang';
        }
 
        function Child(){
            this.age = 28;
        }
        Child.prototype = new Parent();//繼承了Parent,通過原型
 
        var demo = new Child();
        alert(demo.age);
        alert(demo.name);//得到被繼承的屬性
 

Javascript作用鏈域?

全域性函式無法檢視區域性函式的內部細節,但區域性函式可以檢視其上層的函式細節,直至全域性細節。
當需要從區域性函式查詢某一屬性或方法時,如果當前作用域沒有找到,就會上溯到上層作用域查詢,
直至全域性函式,這種組織形式就是作用域鏈。

 

談談This物件的理解。

this總是指向函式的直接呼叫者(而非間接呼叫者);
如果有new關鍵字,this指向new出來的那個物件;
在事件中,this指向觸發這個事件的物件,特殊的是,IE中的attachEvent中的this總是指向全域性物件Window;
 

eval是做什麼的?

它的功能是把對應的字串解析成JS程式碼並執行;

應該避免使用eval,不安全,非常耗效能(2次,一次解析成js語句,一次執行)。

由JSON字串轉換為JSON物件的時候可以用eval,var obj =eval('('+ str +')');
 

null,undefined 的區別?

null        表示一個物件是“沒有值”的值,也就是值為“空”;
undefined   表示一個變數聲明瞭沒有初始化(賦值);
undefined不是一個有效的JSON,而null是;
undefined的型別(typeof)是undefined;
null的型別(typeof)是object;
Javascript將未賦值的變數預設值設為undefined;
Javascript從來不會將變數設為null。它是用來讓程式設計師表明某個用var宣告的變數時沒有值的。
typeof undefined
    //"undefined"
    undefined :是一個表示"無"的原始值或者說表示"缺少值",就是此處應該有一個值,但是還沒有定義。當嘗試讀取時會返回 undefined; 
    例如變數被聲明瞭,但沒有賦值時,就等於undefined
 
typeof null
    //"object"
    null : 是一個物件(空物件, 沒有任何屬性和方法);
    例如作為函式的引數,表示該函式的引數不是物件;
注意:
    在驗證null時,一定要使用 === ,因為 == 無法分別 null 和 undefined
    null == undefined // true
    null === undefined // false

 

什麼是閉包(closure),為什麼要用它?

閉包是指有權訪問另一個函式作用域中變數的函式,建立閉包的最常見的方式就是在一個函式內建立另一個函式,通過另一個函式訪問這個函式的區域性變數,利用閉包可以突破作用鏈域,將函式內部的變數和方法傳遞到外部。
閉包的特性:
1.函式內再巢狀函式
2.內部函式可以引用外層的引數和變數
3.引數和變數不會被垃圾回收機制回收
 
//li節點的onclick事件都能正確的彈出當前被點選的li索引
 <ul id="testUL">
    <li> index = 0</li>
    <li> index = 1</li>
    <li> index = 2</li>
    <li> index = 3</li>
</ul>
<script type="text/javascript">
    var nodes = document.getElementsByTagName("li");
    for(i = 0;i<nodes.length;i+= 1){
        nodes[i].onclick = (function(i){
                  return function() {
                     console.log(i);
                  } //不用閉包的話,值每次都是4
                })(i);
    }
</script>
執行say667()後,say667()閉包內部變數會存在,而閉包內部函式的內部變數不會存在
使得Javascript的垃圾回收機制GC不會收回say667()所佔用的資源
因為say667()的內部函式的執行需要依賴say667()中的變數
這是對閉包作用的非常直白的描述
  function say667() {
    // Local variable that ends up within closure
    var num = 666;
    var sayAlert = function() {
        alert(num);
    }
    num++;
    return sayAlert;
}
 var sayAlert = say667();
 sayAlert()//執行結果應該彈出的667

 

javascript 程式碼中的"use strict";是什麼意思 ? 使用它區別是什麼?

use strict是一種ECMAscript 5 新增的(嚴格)執行模式,這種模式使得 Javascript 在更嚴格的條件下執行,
使JS編碼更加規範化的模式,消除Javascript語法的一些不合理、不嚴謹之處,減少一些怪異行為。
預設支援的糟糕特性都會被禁用,比如不能用with,也不能在意外的情況下給全域性變數賦值;
全域性變數的顯示宣告,函式必須宣告在頂層,不允許在非函式程式碼塊內宣告函式,arguments.callee也不允許使用;
消除程式碼執行的一些不安全之處,保證程式碼執行的安全,限制函式中的arguments修改,嚴格模式下的eval函式的行為和非嚴格模式的也不相同;
提高編譯器效率,增加執行速度;
為未來新版本的Javascript標準化做鋪墊。

 

new操作符具體幹了什麼呢?

1、建立一個空物件,並且 this 變數引用該物件,同時還繼承了該函式的原型。
2、屬性和方法被加入到 this 引用的物件中。
3、新建立的物件由 this 所引用,並且最後隱式的返回 this 
 

JSON 的瞭解?

JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。
它是基於JavaScript的一個子集。資料格式簡單, 易於讀寫, 佔用頻寬小
如:{"age":"12", "name":"back"}
JSON字串轉換為JSON物件:
var obj =eval('('+ str +')');
var obj = str.parseJSON();
var obj = JSON.parse(str);
JSON物件轉換為JSON字串:
var last=obj.toJSONString();
var last=JSON.stringify(obj);
 

Ajax 是什麼? 如何建立一個Ajax?

ajax的全稱:Asynchronous Javascript And XML。
非同步傳輸+js+xml。
所謂非同步,在這裡簡單地解釋就是:向伺服器傳送請求的時候,我們不必等待結果,而是可以同時做其他的事情,等到有了結果它自己會根據設定進行後續操作,與此同時,頁面是不會發生整頁重新整理的,提高了使用者體驗。
 
(1)建立XMLHttpRequest物件,也就是建立一個非同步呼叫物件

(2)建立一個新的HTTP請求,並指定該HTTP請求的方法、URL及驗證資訊

(3)設定響應HTTP請求狀態變化的函式

(4)傳送HTTP請求

(5)獲取非同步呼叫返回的資料

(6)使用JavaScript和DOM實現區域性重新整理

 

Ajax 解決瀏覽器快取問題?

1、在ajax傳送請求前加上 anyAjaxObj.setRequestHeader("If-Modified-Since","0")。
2、在ajax傳送請求前加上 anyAjaxObj.setRequestHeader("Cache-Control","no-cache")。
3、在URL後面加上一個隨機數: "fresh=" + Math.random();。
4、在URL後面加上時間搓:"nowtime=" + new Date().getTime();
5、如果是使用jQuery,直接這樣就可以了 $.ajaxSetup({cache:false})。這樣頁面的所有ajax都會執行這條語句就是不需要儲存快取記錄

 

同步和非同步的區別?

同步的概念應該是來自於OS中關於同步的概念:不同程序為協同完成某項工作而在先後次序上調整(通過阻塞,喚醒等方式).同步強調的是順序性.誰先誰後.非同步則不存在這種順序性.
同步:瀏覽器訪問伺服器請求,使用者看得到頁面重新整理,重新發請求,等請求完,頁面重新整理,新內容出現,使用者看到新內容,進行下一步操作。
非同步:瀏覽器訪問伺服器請求,使用者正常操作,瀏覽器後端進行請求。等請求完,頁面不重新整理,新內容也會出現,使用者看到新內容。
 

如何解決跨域問題?

jsonp、 iframe、window.name、window.postMessage、伺服器上設定代理頁面

 

DOM操作——怎樣新增、移除、移動、複製、建立和查詢節點?

(1)建立新節點
  createDocumentFragment()    //建立一個DOM片段
  createElement()   //建立一個具體的元素
  createTextNode()   //建立一個文字節點
(2)新增、移除、替換、插入
  appendChild()
  removeChild()
  replaceChild()
  insertBefore() //在已有的子節點前插入一個新的子節點
(3)查詢
  getElementsByTagName()    //通過標籤名稱
  getElementsByName()    //通過元素的Name屬性的值(IE容錯能力較強,會得到一個數組,其中包括id等於name值的)
  getElementById()    //通過元素Id,唯一性

JavaScript 的 typeof 返回哪些資料型別?

typeof 返回七種可能的值:“number”、“string”、“boolean”、“object”、"symbol"、“function”和“undefined”。

 

請寫出以下運算結果:

alert(typeof null);  // object
alert(typeof undefined);  // undefined
alert(typeof NaN);  // number
alert(NaN == undefined);  // false
alert(NaN == NaN);  // false
var str = "123abc";
alert(typeof str++);  // number
alert(str);  // NaN
 

例舉至少 3 種強制型別轉換和 2 種隱式型別轉換?

1. 強制型別轉換: 明確呼叫內建函式,強制把一種型別的值轉換為另一種型別。強制型別轉換主要有:BooleanNumberStringparseIntparseFloat
 
2. 隱式型別轉換: 在使用算術運算子時,運算子兩邊的資料型別可以是任意的,比如,一個字串可以和數字相加。之所以不同的資料型別之間可以做運算,是因為 JavaScript 引擎在運算之前會悄悄的把他們進行了隱式型別轉換。隱式型別轉換主要有:+、–、==!

 

BOM 物件有哪些,列舉 window 物件?

  • window 物件,是 JS 的最頂層物件,其他的 BOM 物件都是 window 物件的屬性;
  • location 物件,瀏覽器當前URL資訊;
  • navigator 物件,瀏覽器本身資訊;
  • screen 物件,客戶端螢幕資訊;
  • history 物件,瀏覽器訪問歷史資訊;

HTTP 狀態訊息 200 302 304 403 404 500 分別表示什麼?

  • 200:請求已成功,請求所希望的響應頭或資料體將隨此響應返回。
  • 302:請求的資源臨時從不同的 URI 響應請求。由於這樣的重定向是臨時的,客戶端應當繼續向原有地址傳送以後的請求。只有在 Cache-Control Expires 中進行了指定的情況下,這個響應才是可快取的。
  • 304:如果客戶端傳送了一個帶條件的 GET 請求且該請求已被允許,而文件的內容(自上次訪問以來或者根據請求的條件)並沒有改變,則伺服器應當返回這個狀態碼。304 響應禁止包含訊息體,因此始終以訊息頭後的第一個空行結尾。
  • 403:伺服器已經理解請求,但是拒絕執行它。
  • 404:請求失敗,請求所希望得到的資源未被在伺服器上發現。
  • 500:伺服器遇到了一個未曾預料的狀況,導致了它無法完成對請求的處理。一般來說,這個問題都會在伺服器端的原始碼出現錯誤時出現。

GET和POST的區別,何時使用POST?

GET:一般用於查詢資料,使用URL傳遞引數,由於瀏覽器對位址列長度有限制,所以對使用get方式所傳送資訊的數量有限制,同時瀏覽器會記錄(歷史記錄,快取)中會保留請求地址的資訊,包括地址後面的資料。get 只能傳送普通格式(URL 編碼格式)的資料。

 

POST:一般用於向伺服器傳送資料,對所傳送的資料的大小理論上是沒有限制,瀏覽器會快取記錄地址,但是不會記錄 post 提交的資料。post 可以傳送純文字、URL編碼格式、二進位制格式的字串,形式多樣。

 

在以下情況中,請使用 POST 請求:

  • 以提交為目的的請求(類似語義化,get 表示請求,post 表示提交);
  • 傳送私密類資料(使用者名稱、密碼)(因為瀏覽器快取記錄特性);
  • 向伺服器傳送大量資料(資料大小限制區別);
  • 上傳檔案圖片時(資料型別區別);

 

 

 

從輸入url到得到html的詳細過程

1、瀏覽器根據DNS伺服器得到域名的IP地址

        2、向這個IP的機器傳送HTTP請求

        3、伺服器收到、處理並返回HTTP請求

        4、瀏覽器得到返回內容

JS中陣列基本操作

  • 不會改變原陣列的方法:
    • concat:拼接兩個陣列,返回拼接後的陣列;
    • filter():接收一個函式作為引數,陣列中每個元素執行函式,返回執行該函式時返回true的元素組成的陣列。
    • map: 返回執行函式後組成的陣列;
    • reduce:累加器;
    • slice() 方法返回一個從開始到結束(不包括結束)選擇的陣列的一部分淺拷貝到一個新陣列物件
    • forEach() 方法對陣列的每個元素執行一次提供的函式
    • join() 方法將一個數組(或一個類陣列物件)的所有元素連線成一個字串並返回這個字串。
  • 會改變原陣列
    • pop()刪除尾部元素,返回刪除的元素;
    • push()新增尾部元素,返回陣列長度;
    • shift()刪除頭部元素,返回刪除的元素;
    • unshift()網頭部新增元素,返回長度;
    • splice()新增、刪除,

 

 

 

 

 

 

你怎麼理解同源策略?

  • 同源限制主要是為了安全,如果沒有同源限制存在瀏覽器中的cookie等其他資料可以任意讀取,不同域下DOM任意操作,Ajax任意請求,這會有很嚴重的安全隱患;
  • 為了保護不同站點和使用者的隱私安全,個瀏覽器便制定了同源策略;
  • 所謂同源即要求協議、域名、埠號完全相同;
  • 一般解決跨域的方式常用的有JSONP(只支援 GET 請求)、跨域資源共享CORS(伺服器端通過設定Access-Control-Allow-Origin來進行的)、伺服器端設定代理請求:伺服器端不受同源策略限制

 

閱讀以下程式碼

如果執行上面程式碼,3秒延遲後你會看到,實際上每次列印輸出是4,而不是期望的0123 

 

閱讀以下程式碼

輸出2

 

輸出 undefine 6

分析如下:
開始執行程式碼時,會建立一個全域性物件window
js執行程式碼過程可以分: 詞法分析期和執行期
第一步詞法分析包括:形參分析、實參分析、變數宣告分析、函式宣告分析。分析出的結果作為物件的屬性和方法
window物件在詞法分析期 得到的屬性和方法有:
window.a=function(xx){this.x=xx;return this} 
window.x=undefined
window.y=undefined

程式碼執行期:
/*先執行 window.a(5) =》window.a=function(xx){this.x=xx;return this} 函式中的this指代物件是window.
得出window.x=5,   此時,全域性域中window.x=undefined 變成 window.x=5  
然後   return  window 賦值給 x 即:x=window ,
最終這x=window這句賦值語句 把 window.x=5改成 window.x=window  */
 x=a(5);    
 /*先執行 window.a(6) =》window.a=function(xx){this.x=xx;return this} 函式中的this指代物件是window.
得出window.x=6,   把全域性域中window.x=window變成 window.x=6    
然後   return  window 賦值給 y  即:y=window  
y=window  賦值語句把window.y=undefined 變成了 window.y=window  */
 y=a(6);
//
綜上所述:window.x=6     window.y=window
console.log(x.x);     //輸出x.x 相當於:(window.x).x=6.x------->window物件中沒有 6.x屬性      則輸出undefined
console.log(y.x);      //輸出 y.x 相當於:(window.y).x=window.x------------>window物件中有window.x這個屬性  則輸出6 

 

 

 

閱讀以下程式碼:

 

結果:1 11 show11

 

 

作為物件的方法來呼叫,this指向方法的呼叫者,即母體物件,不管被呼叫的函式,宣告的時候屬於方法,還是函式

 

 

 

 

 

 

 

 

 

閱讀以下程式碼:

 

第一行:

可以得知,第一個fun(0)是在呼叫第一層fun函式。第二個fun(1)是在呼叫前一個fun的返回值的fun函式,所以:

第後面幾個fun(1),fun(2),fun(3),函式都是在呼叫第二層fun函式

遂:

在第一次呼叫fun(0)時,oundefined

第二次呼叫fun(1)m1,此時fun閉包了外層函式的n,也就是第一次呼叫的n=0,即m=1n=0,並在內部呼叫第一層fun函式fun(1,0);所以o0

第三次呼叫fun(2)m2,但依然是呼叫a.fun,所以還是閉包了第一次呼叫時的n,所以內部呼叫第一層的fun(2,0);所以o0

第四次同理;

即:最終答案為undefined,0,0,0

 

第二行

先從fun(0)開始看,肯定是呼叫的第一層fun函式;而他的返回值是一個物件,所以第二個fun(1)呼叫的是第二層fun函式,後面幾個也是呼叫的第二層fun函式。

遂:

在第一次呼叫第一層fun(0)時,oundefined

第二次呼叫 .fun(1)m1,此時fun閉包了外層函式的n,也就是第一次呼叫的n=0,即m=1n=0,並在內部呼叫第一層fun函式fun(1,0);所以o0

第三次呼叫 .fun(2)m2,此時當前的fun函式不是第一次執行的返回物件,而是第二次執行的返回物件。而在第二次執行第一層fun函式時時(1,0)所以n=1,o=0,返回時閉包了第二次的n,遂在第三次呼叫第三層fun函式時m=2,n=1,即呼叫第一層fun函式fun(2,1),所以o1

第四次呼叫 .fun(3)m3,閉包了第三次呼叫的n,同理,最終呼叫第一層fun函式為fun(3,2);所以o2

即最終答案:undefined,0,1,2

 

第三行:

根據前面兩個例子,可以得知:

fun(0)為執行第一層fun函式,.fun(1)執行的是fun(0)返回的第二層fun函式,這裡語句結束,遂c存放的是fun(1)的返回值,而不是fun(0)的返回值,所以c中閉包的也是fun(1)第二次執行的n的值。c.fun(2)執行的是fun(1)返回的第二層fun函式,c.fun(3)執行的fun(1)返回的第二層fun函式。

遂:

在第一次呼叫第一層fun(0)時,oundefined

第二次呼叫 .fun(1)m1,此時fun閉包了外層函式的n,也就是第一次呼叫的n=0,即m=1n=0,並在內部呼叫第一層fun函式fun(1,0);所以o0

第三次呼叫 .fun(2)m2,此時fun閉包的是第二次呼叫的n=1,即m=2n=1,並在內部呼叫第一層fun函式fun(2,1);所以o1

第四次.fun(3)時同理,但依然是呼叫的第二次的返回值,遂最終呼叫第一層fun函式fun(3,1),所以o還為1

即最終答案:undefined,0,1,1