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

英文 | https://betterprogramming.pub/100-javascript-interview-questions-58e22e30f7f1
翻譯 | 楊小二
hello(); // Prints "Hello world! " even though the function is called "before" declarationfunction hello(){console.log("Hello world! ");}
對于變量,提升有點不同。它在作用域的頂部將 undefined 分配給它們。
例如,在定義變量之前調(diào)用它:
console.log(dog);var dog = "Spot";
結(jié)果是:
undefined這可能令人驚訝,因為你可能預(yù)計它會導(dǎo)致錯誤。
如果你聲明一個函數(shù)或變量,無論你在哪里聲明它,它總是被移動到作用域的頂部。
3、isNan() 函數(shù)有什么作用?
你可以使用 isNan() 函數(shù)來檢查值的類型是否為數(shù)字且是否為 NaN。
(是的, NaN 是數(shù)字類型,即使它的名稱是“非數(shù)字”。這是因為它在底層是數(shù)字類型,即使它沒有數(shù)字值。)
例如:
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 中的負(fù)無窮是什么?
如果在 JavaScript 中將負(fù)數(shù)除以零,則會得到負(fù)無窮大。
例如:
console.log(-10/0)輸出:
-Infinity5、 什么是未聲明變量?一個未定義的變量怎么樣?
程序中根本不存在未聲明的變量。如果你的程序嘗試讀取未聲明的變量,則會引發(fā)運行時錯誤。
調(diào)用未聲明變量的示例顯然會導(dǎo)致錯誤:
console.log(dog);輸出:
error: Uncaught ReferenceError: dog is not defined未定義的變量。在程序中聲明但沒有值。如果程序嘗試讀取未定義的變量,則會返回未定義的值并且應(yīng)用程序不會崩潰。
未定義變量的一個例子是:
let car;console.log(car);
輸出:
undefined6、JavaScript 中有哪些類型的彈出框?
三種類型的彈出窗口是警報、確認(rèn)和提示。讓我們看看每個的示例使用:
警報
例如:
window.alert("Hello, world!");確認(rèn)
例如:
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、 == 和 === 有什么區(qū)別?
== 比較值
=== 比較值和類型
例子:
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、隱式類型強制有什么作用?舉個例子。
隱式類型強制意味著一個值在幕后從一種類型轉(zhuǎn)換為另一種類型。當(dāng)表達(dá)式的操作數(shù)是不同類型時會發(fā)生這種情況。
例如,字符串強制意味著在數(shù)字上應(yīng)用運算符 + ,字符串會自動將數(shù)字轉(zhuǎn)換為字符串。
例如:
var x = 1;var y = "2";x + y // Returns "12"
但是在處理減法時,強制以另一種方式起作用。它將字符串轉(zhuǎn)換為數(shù)字。
例如:
var x = 10;var y = "10";x - y // Returns 0
9、JavaScript 是靜態(tài)類型語言還是動態(tài)類型語言?這是什么意思?
JavaScript 是動態(tài)類型的。
這意味著在運行時檢查對象的類型。(在靜態(tài)類型語言中,在編譯時檢查類型。)
換句話說,JavaScript 變量與類型無關(guān)。這意味著你可以毫無問題地更改數(shù)據(jù)類型。
var num = 10;num = "Test";
在靜態(tài)類型語言(例如 C++)中,不可能以這種方式將整數(shù)更改為字符串。
10、JavaScript 中的 NaN 是什么?
NaN 的意思是“非數(shù)字”。這意味著一個值在 JavaScript 中不是正式的數(shù)字。
可能令人困惑的是,使用 typeof() 函數(shù)對 NaN 進(jìn)行類型檢查的結(jié)果是 Number。
console.log(typeof(NaN))輸出:
Number為避免混淆,請使用 isNaN() 來檢查值的類型是否為 NaN 或不是數(shù)字。
11、 JavaScript 中的展開運算符是什么?
展開運算符允許將可迭代對象(數(shù)組/對象/字符串)擴展為單個參數(shù)/元素。讓我們舉個例子來看看這個行為。
function sum(a, b, c) {return a + b + c;}const nums = [15, 25, 35];console.log(sum(...nums));
輸出:
7512、 JavaScript 中的閉包是什么?
JavaScript 中的閉包意味著內(nèi)部函數(shù)可以訪問外部函數(shù)的變量——即使在外部函數(shù)返回之后也是如此。
例如,要創(chuàng)建一個自增 1 的計數(shù)器,你可以使用閉包:
function createCounter() {let counter = 0;function increment() {counter++;console.log(counter);}return increment;}
這里 createCounter() 是外部函數(shù), increment() 是內(nèi)部函數(shù)。現(xiàn)在,你可以按如下方式使用它:
const add = createCounter();add();add();add();
輸出:
123
這是有效的,因為存儲內(nèi)部函數(shù) increment() 的 add 仍然可以訪問 createCounter() 函數(shù)的計數(shù)器變量。
這是可能的,因為 JavaScript 的閉包特性:即使在外部函數(shù)返回之后,內(nèi)部函數(shù)也可以訪問外部函數(shù)的變量。
13、 JavaScript 中如何處理異常?
如果表達(dá)式拋出錯誤,你可以使用 try...catch 語句處理它們。
使用這個結(jié)構(gòu)的想法是嘗試運行一個表達(dá)式,比如一個帶有輸入的函數(shù),并捕獲可能的錯誤。
例如:
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 followinglet day = weekDay(8);console.log(day);}catch (e) { // catch an error if the above try failedlet day = 'unknown';console.log(e);}
14、 什么是網(wǎng)絡(luò)存儲?
Web 存儲是一種 API,它為瀏覽器提供了一種將鍵值對存儲到用戶瀏覽器本地的方法。使用網(wǎng)絡(luò)存儲使這個過程比使用 cookie 更直觀。
Web 存儲提供了兩種存儲數(shù)據(jù)的方式:
本地存儲 - 為客戶端存儲沒有到期日期的數(shù)據(jù)。
會話存儲——只存儲一個會話的數(shù)據(jù)。瀏覽器關(guān)閉時數(shù)據(jù)消失。
以下是如何從 sessionStorage 保存、訪問和刪除項目的示例:
// Save data to sessionStoragesessionStorage.setItem('favoriteColor', 'gray');// Get the color from the sessionStoragelet data = sessionStorage.getItem('favoriteColor');console.log(data);// Remove saved color preset from sessionStoragesessionStorage.removeItem('favoriteColor');// Remove ALL the saved data from sessionStoragesessionStorage.clear();
以下是使用 localStorage 執(zhí)行相同操作的方法:
// Save data to localStoragelocalStorage.setItem('favoriteColor', 'gray');// Get the color from the localStoragelet data = localStorage.getItem('favoriteColor');console.log(data);// Remove saved color preset from localStoragelocalStorage.removeItem('favoriteColor');// Remove ALL the saved data from localStoragelocalStorage.clear();
15、為什么需要網(wǎng)絡(luò)存儲?
Web 存儲(問題 14)可以在本地存儲大量數(shù)據(jù)。關(guān)鍵是它不會影響網(wǎng)站的性能。
使用網(wǎng)絡(luò)存儲,信息不會存儲到服務(wù)器中。與 cookie 相比,這使其成為更可取的方法。
16、什么是模塊?
模塊是可重用代碼的單元。通常,你可以從模塊中將有用的函數(shù)或構(gòu)造函數(shù)導(dǎo)入到你的項目中。
從模塊導(dǎo)入功能可能如下所示:
import { hello } from './modules/helloWorld.js';17、JavaScript 中的“范圍”是什么意思?
范圍定義了“代碼的可見性”。
更正式地說,作用域描述了代碼中可以訪問變量、函數(shù)和其他對象的位置。范圍是在運行時在你的代碼中創(chuàng)建的。
例如,塊作用域表示花括號之間的“區(qū)域”:
if(true) {let word = "Hello";}console.log(word); // ERROR OCCURS
在這里,變量 word 不能從其他任何地方訪問,但在 if 語句中。
18、JavaScript 中的高階函數(shù)是什么?
一個高階函數(shù)對另一個函數(shù)進(jìn)行操作。它要么接受一個函數(shù)作為參數(shù),要么返回另一個函數(shù)。
例如:
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 world19、 JavaScript 中的“this”關(guān)鍵字是什么?
這是指對象本身。
例如:
var student = {name: "Matt",getName: function(){console.log(this.name);}}student.getName();
輸出:
Matt要使 getName() 方法在 student 對象中工作,該對象必須訪問自己的屬性。這可以通過對象內(nèi)的 this 關(guān)鍵字實現(xiàn)。
20、call() 方法有什么作用?
call() 方法可用于在另一個對象上調(diào)用一個對象的方法。
obj1.func.call(obj2)例如:
var student = {name: "Matt",getName: function(){console.log(this.name);}}var anotherStudent = {name: "Sophie"};student.getName.call(anotherStudent);
輸出:
SofieCall() 方法還可用于通過指定所有者對象來調(diào)用函數(shù)。
例如:
function sayHi(){console.log("Hello " + this.name);}var person = {name: "Matt"};sayHi.call(person);
輸出:
Hello Mattcall() 也可以接受參數(shù)。
例如:
function sayHi(adjective){console.log("Hello " + this.name + ", You are " + adjective);}var obj = {name: "Matt"};sayHi.call(obj, "awesome");
輸出:
Hello Matt, you are awesome21、apply() 方法是什么?
apply() 方法的作用與 call() 方法相同。不同之處在于 apply() 方法接受作為數(shù)組的參數(shù)。
例如:
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()函數(shù)中,‘Hello’被分配給greeting,‘How are you?’被分配給message。
22、什么是bind()方法?
bind() 方法返回一個新函數(shù),其 this 已設(shè)置為另一個對象。
與 apply() 和 call() 不同,bind() 不會立即執(zhí)行函數(shù)。相反,它返回一個新版本的函數(shù),其 this 被設(shè)置為另一個值。
讓我們看一個例子:
let person = {name: 'John',getName: function() {console.log(this.name);}};window.setTimeout(person.getName, 1000);
這不會打印名稱“John”,而是打印 undefined。要理解為什么會發(fā)生這種情況,請以等效的方式重寫最后一行:
let func = person.getName;setTimeout(func, 1000);
setTimeout() 與 person 對象分開接收函數(shù),但沒有 person 的名字。因此,當(dāng) setTimeout() 調(diào)用 person.getName 時,名稱是未定義的。
要解決此問題,你需要將 getName() 方法綁定到 person 對象:
let func = person.getName.bind(person);setTimeout(func, 1000);
輸出:
John讓我們檢查一下這種方法是如何工作的:
person.getName 方法綁定到 person 對象。
綁定函數(shù) func 現(xiàn)在將此值設(shè)置為 person 對象。當(dāng)你將這個新綁定函數(shù)傳遞給 setTimeout() 函數(shù)時,它知道如何獲取此人的姓名。
23、什么是柯里化?
柯里化意味著將具有 n 個參數(shù)的函數(shù)轉(zhuǎn)換為具有一個或更少參數(shù)的 n 個函數(shù)。
例如,假設(shè)你有一個將兩個數(shù)字相加的函數(shù) add():
function add(a, b) {return a + b;}
你可以通過以下方式調(diào)用此函數(shù):
add(2,3)然后讓我們咖喱函數(shù):
function add(a) {return function(b) {return a + b;}}
現(xiàn)在你可以通過以下方式調(diào)用這個柯里化函數(shù):
add(2)(3)柯里化不會改變函數(shù)的行為。它改變了它的調(diào)用方式。
24、JavaScript 中的 promise 是什么?
承諾是一個可能在未來產(chǎn)生價值的對象。
承諾始終處于可能的狀態(tài)之一:已完成、拒絕或未決。
創(chuàng)建一個承諾看起來像這樣:
const promise = new Promise(function(resolve, reject) {// implement the promise here})
例如,讓我們創(chuàng)建一個在被調(diào)用后兩秒解析的承諾。
const promise = new Promise(resolve => {setTimeout(() => {resolve("Hello, world!");}, 2000);}, reject => {});
現(xiàn)在 promises 的關(guān)鍵是你可以在使用 .then() 方法解析 promise 后立即執(zhí)行代碼:
promise.then(result => console.log(result));輸出:
Hello, world!Promise 可以鏈接在一起,這樣一個已解決的 Promise 會返回一個新的 Promise。
下面是一個 promise 的流程圖,它也說明了如何鏈接它們:

25、為什么要使用承諾?
在 JavaScript 中,promise 對異步操作很有用。
過去,必須使用回調(diào)來處理異步操作,即在操作完成后立即執(zhí)行的函數(shù)。這導(dǎo)致了“回調(diào)地獄”,一種帶有嵌套回調(diào)的金字塔形代碼。

Promises 通過減少回調(diào)地獄和編寫更干凈的代碼為回調(diào)提供了另一種方法。這是可能的,因為 Promise 可以按以下方式鏈接:

26、JavaScript 中的回調(diào)函數(shù)是什么?
回調(diào)函數(shù)是作為參數(shù)傳遞給另一個函數(shù)的函數(shù)。該函數(shù)在傳遞給它的函數(shù)內(nèi)部執(zhí)行,以在某些操作完成時“回調(diào)”。
讓我們看一個例子:
function greetName(name) {console.log('Hello ' + name);}function askName(callback) {let name = prompt('Enter your name.');callback(name);}askName(greetName);
這段代碼會提示你一個名字,當(dāng)你輸入名字時,它會對該名字說“你好”。因此回調(diào)函數(shù)(在本例中為 greetName)僅在您輸入名稱后執(zhí)行。
27、為什么在 JavaScript 中使用回調(diào)?
回調(diào)很有用,因為 JavaScript 是一種事件驅(qū)動的語言。換句話說,它不是等待響應(yīng),而是在偵聽其他事件的同時繼續(xù)執(zhí)行。
上面的例子演示了 JavaScript 中回調(diào)的用處:
function greetName(name) {console.log('Hello ' + name);}function askName(callback) {let name = prompt('Enter your name.');callback(name);}askName(greetName);
28、JavaScript 中的嚴(yán)格模式是什么?
嚴(yán)格模式允許你設(shè)置程序在嚴(yán)格的上下文中運行。這可以防止執(zhí)行某些操作。此外,還會引發(fā)更多異常。
表達(dá)“嚴(yán)格使用”;告訴瀏覽器啟用嚴(yán)格模式。
例如:
;number = 1000;
這會導(dǎo)致錯誤,因為嚴(yán)格模式會阻止您為未聲明的變量賦值。
29、 什么是立即調(diào)用函數(shù)?
立即調(diào)用函數(shù) (IIFE) 在定義后立即運行。
例如:
(function(){// action here})();
要了解 IIFE 的工作原理,請查看它周圍的括號:
當(dāng) JavaScript 看到關(guān)鍵字 function 時,它假設(shè)有一個函數(shù)聲明即將到來。
但是上面的聲明是無效的,因為函數(shù)沒有名字。
為了解決這個問題,使用了聲明周圍的第一組括號。這告訴解釋器它是一個函數(shù)表達(dá)式,而不是一個聲明。
(function (){// action here;})
(function (){// action here})();
30、什么是cookie?
cookie 是存儲在你計算機上的一個小數(shù)據(jù)包。
例如,網(wǎng)站可以在訪問者的瀏覽器上放置 cookie,以便在用戶下次訪問該頁面時記住登錄憑據(jù)。
在幕后,cookie 是帶有鍵值對的文本文件。要創(chuàng)建、讀取或刪除 cookie,請使用 document.cookie 屬性。
例如,讓我們創(chuàng)建一個保存用戶名的 cookie:
document.cookie = "username=foobar123";31、為什么在 JavaScript 中使用嚴(yán)格模式?
嚴(yán)格模式有助于編寫“安全”的 JavaScript 代碼。這意味著糟糕的語法實踐會轉(zhuǎn)化為真正的錯誤。
例如,嚴(yán)格模式阻止創(chuàng)建全局變量。
要聲明嚴(yán)格模式,請?zhí)砑印皍se strict”;在要在嚴(yán)格模式下的語句之前的語句:
;const sentence = "Hello, this is very strict";
32、雙感嘆號有什么作用?
雙感嘆號將 JavaScript 中的任何內(nèi)容轉(zhuǎn)換為布爾值。
!!true // true!!2 // true!![] // true!!"Test" // true!!false // false!!0 // false!!"" // false
這是有效的,因為 JavaScript 中的任何東西本質(zhì)上都是“真實的”或“虛假的”。
33、如何刪除屬性及其值?
你可以使用 delete 關(guān)鍵字從對象中刪除屬性及其值。
讓我們看一個例子:
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或不存在的引用。
表示沒有變量值。
使用原始操作轉(zhuǎn)換為 0。
undefined:
是表示已聲明但沒有值的變量的值
是未定義的類型。
表示沒有變量。
使用原始操作轉(zhuǎn)換為 NaN。
37、你能用 JavaScript 訪問歷史嗎?
對的,這是可能的。你可以通過包含瀏覽器歷史記錄的 window.history 訪問歷史記錄。
要檢索上一個和下一個 URL,請使用以下方法:
window.history.back()window.history.forward()
38、什么是全局變量?
全局變量在代碼中隨處可見。
要創(chuàng)建全局變量,請省略 var 關(guān)鍵字:
x = 100; // Creates a global variable.此外,如果你在任何函數(shù)之外使用 var 創(chuàng)建變量,你也將創(chuàng)建一個全局變量。
39、 JavaScript 與 Java 有關(guān)系嗎?
不。
它們是兩種不同的編程語言,彼此無關(guān)。
40、什么是 JavaScript 事件?
事件是發(fā)生在 HTML 元素上的事情。在 HTML 頁面中使用 JavaScript 時,它可以對事件做出反應(yīng),例如按鈕單擊。
讓我們創(chuàng)建一個 HTML 頁面,其中有一個按鈕,當(dāng)單擊該按鈕時,會顯示一個警報:
<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 很好地描述了行為。它可以防止事件采取默認(rèn)行為。
例如,你可以在單擊提交按鈕時阻止表單提交:
document.getElementById("link").addEventListener("click", function(event){event.preventDefault()});
42、setTimeout() 方法是什么?
setTimeout() 方法在指定的毫秒數(shù)后調(diào)用函數(shù)(一次)。例如,讓我們在一秒(1000 毫秒)后記錄一條消息:
setTimeout(function() {console.log("Good day");}, 1000);
43、setInterval() 方法是什么?
setInterval() 方法以自定義間隔定期調(diào)用函數(shù)。
例如,讓我們每隔一秒定期記錄一條消息:
setInterval(function() {console.log("Good day");}, 1000);
44、什么是ECMAScript?
ECMAScript 是構(gòu)成 JavaScript 基礎(chǔ)的腳本語言。
ECMAScript 由 ECMA 國際標(biāo)準(zhǔn)組織標(biāo)準(zhǔn)化(查看 ECMA-262 和 ECMA-402 規(guī)范)。
45、什么是JSON?
JSON(JavaScript Object Notation)是一種用于交換數(shù)據(jù)的輕量級數(shù)據(jù)格式。
例如,這是一個 JSON 對象:
{'name': 'Matt','address': 'Imaginary Road 22','age': 32,'married': false,'hobbies': ['Jogging', 'Tennis', 'Padel']}
JSON 的語法規(guī)則是:
數(shù)據(jù)以鍵值對的形式存在。
數(shù)據(jù)以逗號分隔。
花括號定義一個對象。
方括號定義了一個數(shù)組。
46、 JSON 用在什么地方?
當(dāng)向服務(wù)器發(fā)送數(shù)據(jù)時,反之亦然,數(shù)據(jù)必須是文本格式。
JSON 是一種純文本格式,允許將數(shù)據(jù)發(fā)送到服務(wù)器,并將數(shù)據(jù)從服務(wù)器發(fā)送到瀏覽器。幾乎所有編程語言都支持 JSON,因此它也可以與其他語言一起使用。
47、為什么要使用 JSON 字符串化?
當(dāng)你向服務(wù)器發(fā)送數(shù)據(jù)時,它必須是一個字符串。
要將 JavaScript 對象轉(zhuǎn)換為字符串,你可以使用 JSON.stringify() 方法。
var dataJSON = {name: "Matt", age: 51};var dataString = JSON.stringify(dataJSON);console.log(dataString);
'{"name":"Matt","age":51}'48、 如何將 JSON 字符串轉(zhuǎn)換為 JSON 對象?
當(dāng)你從服務(wù)器接收數(shù)據(jù)時,它始終是字符串格式。要將 JSON 字符串轉(zhuǎn)換為 JavaScript 對象,請使用 JSON.parse() 方法。
var data = '{"name":"Matt", "age":51}';var dataJSON = JSON.parse(data);console.log(dataJSON);
{name:"Matt",age:51}
49、如何為變量分配默認(rèn)值?
使用邏輯運算符 || 在賦值中提供一個默認(rèn)值。
const a = b || c;這樣一來,如果 b 為假,那么 c 將被分配給 a。 (Falsy 表示 null、false、undefined、0、空字符串或 NaN。)
50、 你能為函數(shù)定義屬性嗎?
是的,因為函數(shù)也是對象。
讓我們看一個例子:
let func = function(x) {};func.property1 = "Hello there";console.log(func.property1);
輸出:
Hello there學(xué)習(xí)更多技能
請點擊下方公眾號
![]()

