1. 程式人生 > 其它 >JavaScript常見面試問題

JavaScript常見面試問題

基本資料型別中的null和undefined的區別:

null表示“沒有物件”,該處不應該有值;
undefined表示“缺少值”。該處應該有值,但是沒有定義;
轉為數值也不同,null轉為數值為0,undefined轉為數值NaN(不是一個數字);

什麼時候會有null:

1、作為函式的引數,表示該函式的引數不是物件
2、作為物件原型鏈的終點

什麼時候會出現undefined:

1、變數被聲明瞭。但是沒有賦值,就等於undefined.
2、呼叫函式時,應該提供的引數沒有提供,該引數就等於undefined。3、物件沒有賦值的屬性,該屬性的值為undefined。
4、函式沒有返回值時,預設返回undefined。

閉包是什麼

閉包的表現形式

  • 返回一個函式(方法中返回一個方法)
  • 作為函式引數傳遞
  • 回撥函式
  • 非典型閉包IIFE(立即執行函式表示式)

根據詞法作用域的規則,內部函式總是可以訪問其外部函式中宣告的變數,當通過呼叫一個外部函式返回一個內部函式後,即使該外部函式已經執行結束了,但是內部函式引用外部函式的變數依然儲存在記憶體中,我們就把這些變數的集合稱為(該外部函式的)閉包。

閉包是一個定義在其它函式(父函式)裡面的函式,它擁有對父函式裡面變數的訪問權。
閉包擁有如下三個作用域的訪問權:
1.自身的作用域;;2.父作用域;3.全域性作用域

JS防抖與節流

防抖

指觸發事件後在規定時間內回撥函式只能執行一次

,如果在規定時間內觸發了該事件,則會重新開始算規定時間。

節流

一定時間內只調用一次函式;
對於設定的間隔時間(通常為毫秒)內的互動,只響應最新的,之前的全部忽略掉。

應用場景:
1.提交表單。
2.高頻監聽事件

JS中原型,原型鏈與繼承

在JavaScript中,每個函式都有一個prototype屬性,這個屬性指向函式的原型物件。

原型的概念:每一個javascript物件(除null外)建立的時候,就會與之關聯另一個物件,這個物件就是我們所說的原型,每一個物件都會從原型中“繼承”屬性。

原型鏈:原型物件自身也是一個物件,它也有自己的原型物件,這樣層層上溯,就形成了一個類似連結串列的結構,這就是原型鏈

繼承屬性:JavaScript 物件是動態的屬性“包”(指其自己的屬性)。JavaScript 物件有一個指向一個原型物件的鏈。當試圖訪問一個物件的屬性時,它不僅僅在該物件上搜尋,還會搜尋該物件的原型,以及該物件的原型的原型,依次層層向上搜尋,直到找到一個名字匹配的屬性或到達原型鏈的末尾。

繼承方法:JavaScript 並沒有其他基於類的語言所定義的“方法”。在 JavaScript 裡,任何函式都可以新增到物件上作為物件的屬性。函式的繼承與其他的屬性繼承沒有差別,包括上面的“屬性遮蔽”(這種情況相當於其他語言的方法重寫)。

  • 每一個建構函式都擁有一個 prototype 屬性,這個屬性指向一個物件,也就是原型物件
  • 原型物件預設擁有一個 constructor 屬性,指向指向它的那個建構函式
  • 每個物件都擁有一個隱藏的屬性 __proto__,指向它的原型物件

forEach()與map()

forEach()定義:
針對每一個元素執行提供的函式(executes a provided function once for each array element)。除了丟擲異常以外,沒有辦法中止或跳出 forEach() 迴圈。如果你需要中止或跳出迴圈,forEach() 方法不是應當使用的工具。

forEach()方法:針對每一個元素執行提供的函式

map()定義:
建立一個新的陣列,其中每一個元素由呼叫陣列中的每一個元素執行提供的函式得來。map 方法會給原陣列中的每個元素都按順序呼叫一次 callback 函式。callback 每次執行後的返回值(包括 undefined)組合起來形成一個新陣列。 callback 函式只會在有值的索引上被呼叫;那些從來沒被賦過值或者使用 delete 刪除的索引則不會被呼叫。

map()方法:forEach()方法不會返回執行結果,而是undefined。也就是說,forEach()會修改原來的陣列。而map()方法會得到一個新的陣列並返回

區別

forEach()方法不會返回執行結果,而是undefined。也就是說,forEach()會修改原來的陣列。而map()方法會得到一個新的陣列並返回。

filter()

filter也是一個常用的操作,它用於把Array的某些元素過濾掉,然後返回剩下的元素。
和map()類似,Array的filter()也接收一個函式。和map()不同的是,filter()把傳入的函式依次作用於每個元素,然後根據返回值是true還是false決定保留還是丟棄該元素。

注意: filter() 不會對空陣列進行檢測。
注意: filter() 不會改變原始陣列。

JS中型別轉換是怎樣的

在JavaScript中,在兩個不同型別之間的轉換叫做coercion,有兩種形式

顯示轉換

var a = "10";
var b = Number(a);
a;
b;//10 the number

隱式轉換

var a ="10";
var b = a*1;
a;
b;//10 th number

JS中的作用域是怎樣的

在JavaScript中每一個函式都有各自的作用域。作用域可以理解為是一個變數的集合以及相應的如何訪問它的規則。只有在函式內部的變數才可以訪問到該函式域的變數

在同一個作用域內部,變數名必須要唯一。作用域可以巢狀。在最內部的作用域中,可以訪問任何外部作用域中的變數

JS中的相等判斷

JavaScript中的相等判斷有嚴格判斷和帶隱式轉換的

判斷兩種:
嚴格判斷:比如 ===,候不會隱式轉換型別;
抽象判斷:比如: ==,比較的時候會隱式轉換型別

一些簡單的規則:
如果兩邊都是布林型別的值,使用 === ; 如果兩邊是0,“ ”,[ ],使用 === ;所有其它型別使用 == 是安全的

var a = "10";
var b = 10;

a == b;//true
a === b;//false

什麼叫做回撥函式

回撥函式是一個函式,它被作為引數傳入另一個函式,當某些操作結束後,該函式被呼叫

例:當陣列被修改,呼叫回撥函式列印一行日誌

function modifyArray(arr, callback){
// do something to arr here
    arr.push(100) ;
// then execute the callback function that was passed
    callback();
}
var arr = [1,2,3,4,5];
modifyArray( arr,function() {
console.log("array has been modified", arr);
});

" use strict" 到底有何用處?

use strict放在檔案的頂部或則函式的第一行來啟動更加嚴格的檢查來避免失誤引起的錯誤

function doSomething(val){
"use strict";
x = val + 10;//var x = val + 10;
}//會報錯

JavaScript中的值和型別

下面是JavaScript內建的可用型別:

string,umber,boolean、null和undefined,object,symbol (ES6的新語法)

事件冒泡以及如何阻止

事件冒泡的概念是指:在最內層的元素上繫結的事件被觸發後,會按照巢狀的層次由內向外逐步觸發。因此,點選某個孩子節點可能會觸發父節點的事件

一個阻止事件冒泡的辦法就是使用event.stopPropagation(),在IE<9的瀏覽器上使用event.cancelBubble

JavaScript中的let關鍵字

ES6允許你使用let關鍵字來申明塊作用域({...})的變數

如何檢查一個數字是否是整數

最簡單的方法是判斷除以1的餘數是否為0

function isInt(num) {
return num % 1 === 0;
}
console.log(isInt(2));//true
console.log(inInt(2.5));//false

什麼叫Immediately Invoked Function Expressions(IIFE)

IIFE叫做立即執行表示式,顧名思義,該表示式一被建立就立即執行

(function IIFE(){
console.log("Hello!");
})();
//"Hello! "

該方法常用語避免汙染全域性的名稱空間,因為所以在IIFE中使用的變數外部都無法訪問

如何此較JavaScrip中的兩個物件

兩個非基本型別的值,比如物件(包括函式和陣列)都是通過引用的形式來訪問。如果直接通過=來判斷,那麼只會簡單的判斷其引用地址是否相同,而不是它們實際對應的值

如果陣列和字串做比較,那麼陣列會通過逗號拼接轉換為學符串。通過等號判斷的時候,兩個相同的陣列不會相等,但是和相同資料的字串比較反而相等。

如果要深度比較:可以使用第三方庫:比如deep-equa或自己實現一個比較演算法

ES5和ES6的不同點

主要的區別:
箭頭函式和字串嵌入;
常量宣告(Const):如同其它程式語言中的常量一樣,但又有不同;
塊作用域變數:ES6中的新關鍵字let允許開發者將變數的作用域限定在塊級別;
引數預設值:允許在函式定義的時候指定預設的值;
ES6開始支援定義類,建構函式,和extend關鍵字來實現繼承;
for...of 語句用來迭代訪問一個物件的所有屬性;
Spread操作符:用於物件合併;
Promise:提供了一個處理非同步操作的方法;
模組的export和import

defined和not defined的區別

在JavaScript中,如果你嘗試使用不存在的還未申明的變數,會丟擲錯誤var name is not defined。但是如果你用typeof來檢視其型別,會返回undefined

匿名函式和命名函式的區別

匿名函式如果不賦值給某個變數,則無法被呼叫;命名函式再次被賦值就是多此一舉

在JavaScript中如何建立私有變數

可以通過在函式中宣告變數來建立私有變數。因為在函式中,外部無法直接訪問

function func(){
var priv = "secret code" ;
}
console.log(priv);//throws error

原型模式(Prototype Design Pattern)

原型模式會建立一個新的物件,但不是建立一個未初始化的物件,而是通過拷貝原型鏈上的值或則被拷貝物件的值來完成初始化。傳統的語言很少使用原型模式,但是JavaScript作為個基於原型的語言,使用原型模式來建立新的物件

判斷給定的字串是否同態(isomorphic)

首先介紹什麼叫做同態:兩個字串,如果A字串中的每個字元都可以在B字串中找到唯一對應,並且順序一一對應;如果存在這樣的函式,那麼A和B同態:paper和title同態;egg和sad不同態;dgg和add同態。

isIsomorphic("egg", 'add '); // true
isIsomorphic( "paper", 'title'); // true
isIsomorphic("kick", 'side'); // false
function isIsomorphic(firstString, secondString) {
    // Check if the same length. If not,they cannot be isomorphic
    if (firstString.length !== secondString.length) return false
}
var letterMap = {};
for (var i = 0; i < firstString.length; i++) {
    var letterA = firststring[i],
        letterB = secondstring[i];
if (letterMap[letterA] === undefined) {
    letterMap[letterA] = letterB;
}else if ( letterMap[letterA] !== letterB) {
    return false;
}
}
return true;
}

Transpiling代表了什麼意思

Transpiling是transforming + compiling的合成詞。對於一些新的語法,瀏覽器還不支援。最好的辦法就是將其變換到舊的等價的程式碼,這個過程通常叫做transpiling

JavaaScript中提升(hoisting)是什麼意思?

提升(hoisting)是指JavaScript的直譯器將所有的變數和函式宣告都提升到該作用域的頂部,有兩種提升型別:變數提升;函式提升。