天天看點

100 個 JavaScript 面試題和答案(上)

100 個 JavaScript 面試題和答案(上)

英文 | https://betterprogramming.pub/100-javascript-interview-questions-58e22e30f7f1

翻譯 | 楊小二

這是一份包含 100 道程式設計面試問題和答案的完整清單。除了面試之外,如果你正在學習或者準備JavaScript考試,這個清單也會很友善。

即使你沒有參加程式設計面試或考試,這份清單也是值得的——它涵蓋了 JavaScript 的大部分重要概念。

現在,讓我們開始吧。

1、什麼是 JavaScript?

JavaScript 是一種用戶端/伺服器端程式設計語言。JavaScript 可以插入到 HTML 中,使網頁具有互動性并實作使用者參與。

2、JavaScript 中的提升是什麼?

提升意味着所有的聲明都被移動到作用域的頂部。這發生在代碼運作之前。

對于函數,這意味着你可以從作用域中的任何位置調用它們,甚至在它們被定義之前。

hello();  // Prints "Hello world! " even though the function is called "before" declaration


function hello(){ 
  console.log("Hello world! ");
}      

對于變量,提升有點不同。它在作用域的頂部将 undefined 配置設定給它們。

例如,在定義變量之前調用它:

console.log(dog);
var dog = "Spot";      

結果是:

undefined      

這可能令人驚訝,因為你可能預計它會導緻錯誤。

如果你聲明一個函數或變量,無論你在哪裡聲明它,它總是被移動到作用域的頂部。

3、isNan() 函數有什麼作用?

你可以使用 isNan() 函數來檢查值的類型是否為數字且是否為 NaN。

(是的, NaN 是數字類型,即使它的名稱是“非數字”。這是因為它在底層是數字類型,即使它沒有數字值。)

例如:

function toPounds(kilos) {
  if (isNaN(kilos)) {
    return 'Not a Number! Cannot be a weight.';
  }
  return kilos * 2.2;
}


console.log(toPounds('this is a test'));
console.log(toPounds('100'));      

輸出:

Not a Number! Cannot be a weight.
220.00000000000003      

4、JavaScript 中的負無窮是什麼?

如果在 JavaScript 中将負數除以零,則會得到負無窮大。

例如:

console.log(-10/0)      

輸出:

-Infinity      

5、 什麼是未聲明變量?一個未定義的變量怎麼樣?

程式中根本不存在未聲明的變量。如果你的程式嘗試讀取未聲明的變量,則會引發運作時錯誤。

調用未聲明變量的示例顯然會導緻錯誤:

console.log(dog);      

輸出:

error: Uncaught ReferenceError: dog is not defined      
  • 未定義的變量。在程式中聲明但沒有值。如果程式嘗試讀取未定義的變量,則會傳回未定義的值并且應用程式不會崩潰。

未定義變量的一個例子是:

let car;
console.log(car);      

輸出:

undefined      

6、JavaScript 中有哪些類型的彈出框?

三種類型的彈出視窗是警報、确認和提示。讓我們看看每個的示例使用:

警報

例如:

window.alert("Hello, world!");      

确認

例如:

if (window.confirm("Are you sure you want to go?")) {
  window.open("exit.html", "See you again!");
}      

提示

例如:

let person = window.prompt("Enter your name");
if (person != null) {
  console.log('Hello', person);
}      

7、 == 和 === 有什麼差別?

== 比較值

=== 比較值和類型

例子:

var x = 100;
var y = "100";


(x == y)  // --> true because the value of x and y are the same


(x === y) // --> false because the type of x is "number" and type of y is "string"      

8、隐式類型強制有什麼作用?舉個例子。

隐式類型強制意味着一個值在幕後從一種類型轉換為另一種類型。當表達式的操作數是不同類型時會發生這種情況。

例如,字元串強制意味着在數字上應用運算符 + ,字元串會自動将數字轉換為字元串。

例如:

var x = 1;
var y = "2";


x + y // Returns "12"      

但是在處理減法時,強制以另一種方式起作用。它将字元串轉換為數字。

例如:

var x = 10;
var y = "10";


x - y // Returns 0      

9、JavaScript 是靜态類型語言還是動态類型語言?這是什麼意思?

JavaScript 是動态類型的。

這意味着在運作時檢查對象的類型。(在靜态類型語言中,在編譯時檢查類型。)

換句話說,JavaScript 變量與類型無關。這意味着你可以毫無問題地更改資料類型。

var num = 10;
num = "Test";      

在靜态類型語言(例如 C++)中,不可能以這種方式将整數更改為字元串。

10、JavaScript 中的 NaN 是什麼?

NaN 的意思是“非數字”。這意味着一個值在 JavaScript 中不是正式的數字。

可能令人困惑的是,使用 typeof() 函數對 NaN 進行類型檢查的結果是 Number。

console.log(typeof(NaN))      

輸出:

Number      

為避免混淆,請使用 isNaN() 來檢查值的類型是否為 NaN 或不是數字。

11、 JavaScript 中的展開運算符是什麼?

展開運算符允許将可疊代對象(數組/對象/字元串)擴充為單個參數/元素。讓我們舉個例子來看看這個行為。

function sum(a, b, c) {
  return a + b + c;
}
const nums = [15, 25, 35];
console.log(sum(...nums));      

輸出:

75      

12、 JavaScript 中的閉包是什麼?

JavaScript 中的閉包意味着内部函數可以通路外部函數的變量——即使在外部函數傳回之後也是如此。

例如,要建立一個自增 1 的計數器,你可以使用閉包:

function createCounter() {
   let counter = 0;
   function increment() {
     counter++;
     console.log(counter);
   }
   return increment;
}      

這裡 createCounter() 是外部函數, increment() 是内部函數。現在,你可以按如下方式使用它:

const add = createCounter();
add();
add();
add();      

輸出:

1
2
3      

這是有效的,因為存儲内部函數 increment() 的 add 仍然可以通路 createCounter() 函數的計數器變量。

這是可能的,因為 JavaScript 的閉包特性:即使在外部函數傳回之後,内部函數也可以通路外部函數的變量。

13、 JavaScript 中如何處理異常?

如果表達式抛出錯誤,你可以使用 try...catch 語句處理它們。

使用這個結構的想法是嘗試運作一個表達式,比如一個帶有輸入的函數,并捕獲可能的錯誤。

例如:

function weekDay(dayNum) {
  if (dayNum < 1 || dayNum > 7) {
    throw 'InvalidDayNumber'
  } else {
    return ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'][dayNum - 1];
  }
}


try { // Try to run the following
  let day = weekDay(8);
  console.log(day);
}
catch (e) { // catch an error if the above try failed
  let day = 'unknown';
  console.log(e);
}      

14、 什麼是網絡存儲?

Web 存儲是一種 API,它為浏覽器提供了一種将鍵值對存儲到使用者浏覽器本地的方法。使用網絡存儲使這個過程比使用 cookie 更直覺。

Web 存儲提供了兩種存儲資料的方式:

本地存儲 - 為用戶端存儲沒有到期日期的資料。

會話存儲——隻存儲一個會話的資料。浏覽器關閉時資料消失。

以下是如何從 sessionStorage 儲存、通路和删除項目的示例:

// Save data to sessionStorage
sessionStorage.setItem('favoriteColor', 'gray');


// Get the color from the sessionStorage
let data = sessionStorage.getItem('favoriteColor');
console.log(data);


// Remove saved color preset from sessionStorage
sessionStorage.removeItem('favoriteColor');


// Remove ALL the saved data from sessionStorage
sessionStorage.clear();      

以下是使用 localStorage 執行相同操作的方法:

// Save data to localStorage
localStorage.setItem('favoriteColor', 'gray');


// Get the color from the localStorage
let data = localStorage.getItem('favoriteColor');
console.log(data);


// Remove saved color preset from localStorage
localStorage.removeItem('favoriteColor');


// Remove ALL the saved data from localStorage
localStorage.clear();      

15、為什麼需要網絡存儲?

Web 存儲(問題 14)可以在本地存儲大量資料。關鍵是它不會影響網站的性能。

使用網絡存儲,資訊不會存儲到伺服器中。與 cookie 相比,這使其成為更可取的方法。

16、什麼是子產品?

子產品是可重用代碼的單元。通常,你可以從子產品中将有用的函數或構造函數導入到你的項目中。

從子產品導入功能可能如下所示:

import { hello } from './modules/helloWorld.js';      

17、JavaScript 中的“範圍”是什麼意思?

範圍定義了“代碼的可見性”。

更正式地說,作用域描述了代碼中可以通路變量、函數和其他對象的位置。範圍是在運作時在你的代碼中建立的。

例如,塊作用域表示花括号之間的“區域”:

if(true) {
   let word = "Hello";
}
console.log(word); // ERROR OCCURS      

在這裡,變量 word 不能從其他任何地方通路,但在 if 語句中。

18、JavaScript 中的高階函數是什麼?

一個高階函數對另一個函數進行操作。它要麼接受一個函數作為參數,要麼傳回另一個函數。

例如:

function runThis(inputFunction) {
  inputFunction();
}


runThis(function() { console.log("Hello world") });      

輸出:

Hello world      

另外一個示例:

function giveFunction() {
  return function() {
    console.log("Hello world")
  }
}


var action = giveFunction();
action()      

輸出:

Hello world      

19、 JavaScript 中的“this”關鍵字是什麼?

這是指對象本身。

例如:

var student = {
    name:  "Matt",
    getName: function(){
      console.log(this.name);
    }
}


student.getName();      

輸出:

Matt      

要使 getName() 方法在 student 對象中工作,該對象必須通路自己的屬性。這可以通過對象内的 this 關鍵字實作。

20、call() 方法有什麼作用?

call() 方法可用于在另一個對象上調用一個對象的方法。

obj1.func.call(obj2)      

例如:

var student = {
  name: "Matt",
  getName: function(){
    console.log(this.name);
  }
}


var anotherStudent = {
  name: "Sophie"
};


student.getName.call(anotherStudent);      

輸出:

Sofie      

Call() 方法還可用于通過指定所有者對象來調用函數。

例如:

function sayHi(){
  console.log("Hello " + this.name);
}


var person = {name: "Matt"};


sayHi.call(person);      

輸出:

Hello Matt      

call() 也可以接受參數。

例如:

function sayHi(adjective){
  console.log("Hello " + this.name + ", You are " + adjective);
}


var obj = {name: "Matt"};


sayHi.call(obj, "awesome");      

輸出:

Hello Matt, you are awesome      

21、apply() 方法是什麼?

apply() 方法的作用與 call() 方法相同。不同之處在于 apply() 方法接受作為數組的參數。

例如:

const person = {
    name: 'John'
}


function greet(greeting, message) {
    return `${greeting} ${this.name}. ${message}`;
}


let result = greet.apply(person, ['Hello', 'How are you?']);


console.log(result);      

輸出:

Hello John. How are you?      

在行中:

let result = greet.apply(person, ['Hello', 'How are you?']);      

在greet()函數中,‘Hello’被配置設定給greeting,‘How are you?’被配置設定給message。

22、什麼是bind()方法?

bind() 方法傳回一個新函數,其 this 已設定為另一個對象。

與 apply() 和 call() 不同,bind() 不會立即執行函數。相反,它傳回一個新版本的函數,其 this 被設定為另一個值。

讓我們看一個例子:

let person = {
    name: 'John',
    getName: function() {
        console.log(this.name);
    }
};


window.setTimeout(person.getName, 1000);      

這不會列印名稱“John”,而是列印 undefined。要了解為什麼會發生這種情況,請以等效的方式重寫最後一行:

let func = person.getName;
setTimeout(func, 1000);      

setTimeout() 與 person 對象分開接收函數,但沒有 person 的名字。是以,當 setTimeout() 調用 person.getName 時,名稱是未定義的。

要解決此問題,你需要将 getName() 方法綁定到 person 對象:

let func = person.getName.bind(person);
setTimeout(func, 1000);      

輸出:

John      

讓我們檢查一下這種方法是如何工作的:

person.getName 方法綁定到 person 對象。

綁定函數 func 現在将此值設定為 person 對象。當你将這個新綁定函數傳遞給 setTimeout() 函數時,它知道如何擷取此人的姓名。

23、什麼是柯裡化?

柯裡化意味着将具有 n 個參數的函數轉換為具有一個或更少參數的 n 個函數。

例如,假設你有一個将兩個數字相加的函數 add():

function add(a, b) {
    return a + b;
}      

你可以通過以下方式調用此函數:

add(2,3)      

然後讓我們咖喱函數:

function add(a) {
  return function(b) {
    return a + b;
  }
}      

現在你可以通過以下方式調用這個柯裡化函數:

add(2)(3)      

柯裡化不會改變函數的行為。它改變了它的調用方式。

24、JavaScript 中的 promise 是什麼?

承諾是一個可能在未來産生價值的對象。

承諾始終處于可能的狀态之一:已完成、拒絕或未決。

建立一個承諾看起來像這樣:

const promise = new Promise(function(resolve, reject) {
    // implement the promise here
})      

例如,讓我們建立一個在被調用後兩秒解析的承諾。

const promise = new Promise(resolve => {
  setTimeout(() => {
    resolve("Hello, world!");
  }, 2000);
}, reject => {});      

現在 promises 的關鍵是你可以在使用 .then() 方法解析 promise 後立即執行代碼:

promise.then(result => console.log(result));      

輸出:

Hello, world!      

Promise 可以連結在一起,這樣一個已解決的 Promise 會傳回一個新的 Promise。

下面是一個 promise 的流程圖,它也說明了如何連結它們:

100 個 JavaScript 面試題和答案(上)

25、為什麼要使用承諾?

在 JavaScript 中,promise 對異步操作很有用。

過去,必須使用回調來處理異步操作,即在操作完成後立即執行的函數。這導緻了“回調地獄”,一種帶有嵌套回調的金字塔形代碼。

100 個 JavaScript 面試題和答案(上)

Promises 通過減少回調地獄和編寫更幹淨的代碼為回調提供了另一種方法。這是可能的,因為 Promise 可以按以下方式連結:

100 個 JavaScript 面試題和答案(上)

26、JavaScript 中的回調函數是什麼?

回調函數是作為參數傳遞給另一個函數的函數。該函數在傳遞給它的函數内部執行,以在某些操作完成時“回調”。

讓我們看一個例子:

function greetName(name) {
  console.log('Hello ' + name);
}


function askName(callback) {
  let name = prompt('Enter your name.');
  callback(name);
}


askName(greetName);      

這段代碼會提示你一個名字,當你輸入名字時,它會對該名字說“你好”。是以回調函數(在本例中為 greetName)僅在您輸入名稱後執行。

27、為什麼在 JavaScript 中使用回調?

回調很有用,因為 JavaScript 是一種事件驅動的語言。換句話說,它不是等待響應,而是在偵聽其他事件的同時繼續執行。

上面的例子示範了 JavaScript 中回調的用處:

function greetName(name) {
  console.log('Hello ' + name);
}


function askName(callback) {
  let name = prompt('Enter your name.');
  callback(name);
}


askName(greetName);      

28、JavaScript 中的嚴格模式是什麼?

嚴格模式允許你設定程式在嚴格的上下文中運作。這可以防止執行某些操作。此外,還會引發更多異常。

表達“嚴格使用”;告訴浏覽器啟用嚴格模式。

例如:

"use strict";
number = 1000;      

這會導緻錯誤,因為嚴格模式會阻止您為未聲明的變量指派。

29、 什麼是立即調用函數?

立即調用函數 (IIFE) 在定義後立即運作。

例如:

(function(){ 
  // action here
})();      

要了解 IIFE 的工作原理,請檢視它周圍的括号:

當 JavaScript 看到關鍵字 function 時,它假設有一個函數聲明即将到來。

但是上面的聲明是無效的,因為函數沒有名字。

為了解決這個問題,使用了聲明周圍的第一組括号。這告訴解釋器它是一個函數表達式,而不是一個聲明。

(function (){
   // action here;
})      

然後,要調用該函數,需要在函數聲明的末尾添加另一組括号。這類似于調用任何其他函數:

(function (){
  // action here
})();      

30、什麼是cookie?

cookie 是存儲在你計算機上的一個小資料包。

例如,網站可以在通路者的浏覽器上放置 cookie,以便在使用者下次通路該頁面時記住登入憑據。

在幕後,cookie 是帶有鍵值對的文本檔案。要建立、讀取或删除 cookie,請使用 document.cookie 屬性。

例如,讓我們建立一個儲存使用者名的 cookie:

document.cookie = "username=foobar123";      

31、為什麼在 JavaScript 中使用嚴格模式?

嚴格模式有助于編寫“安全”的 JavaScript 代碼。這意味着糟糕的文法實踐會轉化為真正的錯誤。

例如,嚴格模式阻止建立全局變量。

要聲明嚴格模式,請添加“use strict”;在要在嚴格模式下的語句之前的語句:

'use strict';
const sentence = "Hello, this is very strict";      

32、雙感歎号有什麼作用?

雙感歎号将 JavaScript 中的任何内容轉換為布爾值。

!!true    // true
!!2       // true
!![]      // true
!!"Test"  // true


!!false   // false
!!0       // false
!!""      // false      

這是有效的,因為 JavaScript 中的任何東西本質上都是“真實的”或“虛假的”。

33、如何删除屬性及其值?

你可以使用 delete 關鍵字從對象中删除屬性及其值。

讓我們看一個例子:

var student = {name: "John", age:20};
delete student.age;


console.log(student);      

輸出:

{name: "John"}      

34、如何在 JavaScript 中檢查變量的類型?

使用 typeof 運算符。

typeof "John Abraham"  // Returns "string"
typeof 100             // Returns "number"      

35、JavaScript 中的 null 是什麼?

null 表示沒有值。它突出顯示變量不指向任何對象。

null 的類型是一個對象:

var name = null;
console.log(typeof(name))      

36、Null vs undefined?

null:

  • 是一個值,訓示變量不指向任何對象。
  • 是對象類型。
  • 表示 null、null或不存在的引用。
  • 表示沒有變量值。
  • 使用原始操作轉換為 0。

undefined:

  • 是表示已聲明但沒有值的變量的值
  • 是未定義的類型。
  • 表示沒有變量。
  • 使用原始操作轉換為 NaN。

37、你能用 JavaScript 通路曆史嗎?

對的,這是可能的。你可以通過包含浏覽器曆史記錄的 window.history 通路曆史記錄。

要檢索上一個和下一個 URL,請使用以下方法:

window.history.back()
window.history.forward()      

38、什麼是全局變量?

全局變量在代碼中随處可見。

要建立全局變量,請省略 var 關鍵字:

x = 100; // Creates a global variable.      

此外,如果你在任何函數之外使用 var 建立變量,你也将建立一個全局變量。

39、 JavaScript 與 Java 有關系嗎?

不。

它們是兩種不同的程式設計語言,彼此無關。

40、什麼是 JavaScript 事件?

事件是發生在 HTML 元素上的事情。在 HTML 頁面中使用 JavaScript 時,它可以對事件做出反應,例如按鈕單擊。

讓我們建立一個 HTML 頁面,其中有一個按鈕,當單擊該按鈕時,會顯示一個警報:

<!doctype html>


<html>
 <head>
   <script>
     function sayHi() {
       alert('Hi, how are you?');
     }
</script>
 </head>


 <body>
   <button type="button" onclick="sayHi()">Click here</button>
 </body>


</html>      

41、preventDefault() 方法有什麼作用?

preventDefault() 取消一個方法。名稱 preventDefault 很好地描述了行為。它可以防止事件采取預設行為。

例如,你可以在單擊送出按鈕時阻止表單送出:

document.getElementById("link").addEventListener("click", function(event){
  event.preventDefault()
});      

42、setTimeout() 方法是什麼?

setTimeout() 方法在指定的毫秒數後調用函數(一次)。例如,讓我們在一秒(1000 毫秒)後記錄一條消息:

setTimeout(function() {
    console.log("Good day");
}, 1000);      

43、setInterval() 方法是什麼?

setInterval() 方法以自定義間隔定期調用函數。

例如,讓我們每隔一秒定期記錄一條消息:

setInterval(function() {
    console.log("Good day");
}, 1000);      

44、什麼是ECMAScript?

ECMAScript 是構成 JavaScript 基礎的腳本語言。

ECMAScript 由 ECMA 國際标準組織标準化(檢視 ECMA-262 和 ECMA-402 規範)。

45、什麼是JSON?

JSON(JavaScript Object Notation)是一種用于交換資料的輕量級資料格式。

例如,這是一個 JSON 對象:

{
    'name': 'Matt',
    'address': 'Imaginary Road 22',
    'age': 32,
    'married': false,
    'hobbies': ['Jogging', 'Tennis', 'Padel']
}      

JSON 的文法規則是:

  • 資料以鍵值對的形式存在。
  • 資料以逗号分隔。
  • 花括号定義一個對象。
  • 方括号定義了一個數組。

46、 JSON 用在什麼地方?

當向伺服器發送資料時,反之亦然,資料必須是文本格式。

JSON 是一種純文字格式,允許将資料發送到伺服器,并将資料從伺服器發送到浏覽器。幾乎所有程式設計語言都支援 JSON,是以它也可以與其他語言一起使用。

47、為什麼要使用 JSON 字元串化?

當你向伺服器發送資料時,它必須是一個字元串。

要将 JavaScript 對象轉換為字元串,你可以使用 JSON.stringify() 方法。

var dataJSON = {name: "Matt", age: 51};
var dataString = JSON.stringify(dataJSON);
console.log(dataString);      

輸出:

'{"name":"Matt","age":51}'      

48、 如何将 JSON 字元串轉換為 JSON 對象?

當你從伺服器接收資料時,它始終是字元串格式。要将 JSON 字元串轉換為 JavaScript 對象,請使用 JSON.parse() 方法。

var data = '{"name":"Matt", "age":51}';
var dataJSON = JSON.parse(data);
console.log(dataJSON);      

輸出:

{
    name:"Matt",
    age:51
}      

49、如何為變量配置設定預設值?

使用邏輯運算符 || 在指派中提供一個預設值。

const a = b || c;      

這樣一來,如果 b 為假,那麼 c 将被配置設定給 a。 (Falsy 表示 null、false、undefined、0、空字元串或 NaN。)

50、 你能為函數定義屬性嗎?

是的,因為函數也是對象。

讓我們看一個例子:

let func = function(x) {


};
func.property1 = "Hello there";
console.log(func.property1);      

輸出:

Hello there      

PS:因為文章篇幅關系,今天先分享前面50道面試題,剩下的50道題目放在下篇裡,敬請繼續關注。

學習更多技能

請點選下方公衆号

100 個 JavaScript 面試題和答案(上)

繼續閱讀