天天看點

100道JavaScript 面試題和答案(下)

100道JavaScript 面試題和答案(下)

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

翻譯 | 楊小二

接上篇《​​100 個 JavaScript 面試題和答案(上)​​》的内容,今天開始後面50道JavaScript面試題。

51、promise中的race方法是什麼意思?

Promise.race() 方法傳回首先解決或拒絕的承諾。

讓我們通過一個例子來證明這一點,其中第二個承諾比第一個更快解決:

let p1 = new Promise(function(resolve, reject) {
    setTimeout(resolve, 500, 'the first promise');
});
let p2 = new Promise(function(resolve, reject) {
    setTimeout(resolve, 100, 'the second promise');
});
Promise.race([p1, p2]).then(function(value) {
console.log(value, 'was faster');
});      

輸出:

the second promise was faster      

52、 promise.all() 方法有什麼作用?

Promise.all 是一個将一系列承諾作為輸入的承諾。它在以下情況下得到解決:

要麼所有的輸入承諾都得到解決。

或者他們中的任何一個被拒絕。

例如, promise.all 等待所有這三個 promise 完成:

var prom1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Yay!");
  }, 1000);
});
var prom2 = Promise.resolve(10);
var prom3 = 100;
Promise.all([prom1, prom2, prom3]).then(values => {
console.log(values);
});      

一秒後輸出:

["Yay", 10, 100]      

53、 eval() 函數是什麼?

eval() 函數計算字元串中的代碼。要計算的字元串可以是表達式、變量、語句或語句序列。

例如:

console.log(eval("5+10"));      

輸出:

15      

54、什麼是事件冒泡?

在事件冒泡中,事件通過最裡面的元素運作事件處理程式開始。然後它觸發父母的事件處理程式,直到它到達最外面的元素。

看到這一點的最佳方法是建立一個在 div 中包含 div 的 HTML 文檔:

<style>
body * {
margin: 20px;
border: 1px solid blue;
  }
</style>
<div notallow="alert('Outer layer')">Outer layer
<div notallow="alert('Middle layer')">Middle layer
<div notallow="alert('Inner layer')">Inner layer
</div>
</div>
</div>      

在每個 div 中,都有一個 JavaScript 警報,當單擊該 div 時會觸發該警報。

結果頁面如下所示:

100道JavaScript 面試題和答案(下)

如果你現在單擊内層,它會觸發配置設定給該 div 的警報,并觸發父 div 的警報。

55、 什麼是時間死區?

時間死區意味着變量不可達,即使它已經在範圍内。

讓我們首先看看,當你嘗試将未初始化的變量記錄到控制台時會發生什麼:

console.log(x);
var x = "Yay";      

輸出:

undefined      

你可能希望這會導緻錯誤,但它會列印 undefined。

發生這種情況是因為所有聲明都被移到了作用域的頂部。由于提升,上面的代碼在引擎蓋下的行為如下:

var x;
console.log(x);
x = "Yay";      

這裡 undefined 被自動配置設定給頂部的變量。這使得在定義它之前使用它成為可能。

但是讓我們看看當我們使用 let 而不是 var 做同樣的事情時會發生什麼:

console.log(x);
let x = 10;      

輸出:

error: Uncaught ReferenceError: Cannot access 'x' before initialization      

發生這種情況是因為 let 的提升方式與 var 不同。當一個 let 變量被提升時,它不會變成未定義的。相反,它是無法通路的,或者在被配置設定值之前處于時間死區。

56、什麼是URI?

URI 或統一資源辨別符是一組區分資源的字元。URI 允許網際網路協定在資源之間執行操作。

URI 可能如下所示:

hello://example.com:8042/there?name=jack#sumthing      

57、什麼是DOM?

當網頁加載完畢後,浏覽器會為該頁面建立一個 DOM。這使 JavaScript 能夠建立動态 HTML。

DOM 或文檔對象模型充當 HTML 文檔的 API。它定義了文檔的結構。它還指定如何通路和修改文檔。

58、文檔加載還是 DOMContentLoaded?

DOMContentLoaded 事件在 HTML 文檔被加載和解析後被觸發。它不會等待資産(例如樣式表和圖像)。

文檔加載事件僅在整個頁面加載後觸發,包括所有資産。

例如,以下是如何使用 DOMContentLoaded 在 DOM 已完全加載時發出通知:

window.addEventListener('DOMContentLoaded', (event) => {
console.log('DOM is now loaded!');
});      

這是一個如何為特定頁面加載時添加偵聽器的示例:

window.addEventListener('load', (event) => {
console.log('The page is now loaded!');
});      

59、HTML 屬性 vs DOM 屬性?

當你編寫 HTML 時,你可以在 HTML 元素上定義屬性。然後,當你使用浏覽器打開頁面時,你的 HTML 代碼将被解析。

至此,一個DOM節點就建立好了。這個 DOM 節點對應于你剛剛編寫的 HTML 文檔。這個 DOM 節點是一個具有屬性的對象。

例如,這個 HTML 元素:

<input id="my-input" type="text" value="Name:">      

具有三個屬性,id、type 和 value。

當浏覽器解析這個 HTML 元素時。

它接受這個輸入字段并從中烘焙一個 HTMLInputElement 對象。

這個對象有幾十個屬性,比如accept、accesKey、align。

它還将一些原始 HTML 屬性轉換為屬性,例如 id 和類型。但是例如, value 屬性不引用 value 屬性。

60、什麼是同源政策?

同源政策是一種有價值的安全機制。它可以防止 JavaScript 跨越域邊界送出請求。

源是指 URI 方案、主機名和端口号。同源政策使得一個頁面上的腳本無法通路另一頁面上的敏感資料。

61、JavaScript 是編譯型語言還是解釋型語言?

JavaScript 是一種解釋型語言。

浏覽器中的解釋器讀取 JavaScript 代碼,解釋每一行,然後運作它。

62、JavaScript 是區分大小寫的語言嗎?

JavaScript 是一種區分大小寫的語言。

關鍵字、變量、函數名等需要大寫一緻。

為了示範,這段代碼有效

let i = 1;
while(i < 2) {
  console.log(i);
  i++;
}      

但這不是,因為 while 是大寫的,即使它不應該。

let i = 1;
WHILE(i < 2) {
console.log(i);
  i++;
}      

63、JavaScript 有多少個線程?

JavaScript 使用單個線程。它不允許編寫解釋器可以在多個線程或程序中并行運作的代碼。

這意味着它按順序執行代碼,并且必須先執行完一段代碼,然後才能轉到下一段代碼。

看到這一點的一個很好的例子是當你在網頁上顯示警報時。警報彈出後,在警報關閉之前,你無法與頁面互動。

alert("Hello there!");      

64、 “break”語句有什麼作用?

break 語句跳出循環并繼續執行循環外的代碼。

例如,此循環在遇到數字 5 後終止:

for (var i = 0; i < 100; i++) {
if (i === 5) {
break;
  }
console.log('Number is ', i);
}
console.log('Yay');      
Number is 0
Number is 1
Number is 2
Number is 3
Number is 4
Yay      

65、 “continue”語句的作用是什麼?

continue 語句跳過一輪循環。

例如,這個循環跳過數字 2 和 3:

for (var i = 0; i < 5; i++) {
  if (i === 2 || i === 3) {
    continue;
  }
  console.log('Number is ', i);
}      

輸出:

0
1
4      

66、什麼是正規表達式?

正規表達式,也稱為 regex 或 regexp,是形成搜尋模式的一組字元。它是一種常用于 JavaScript 和其他程式設計語言的模式比對工具。

例如,讓我們使用正規表達式從字元串中查找任何數字:

var regex = /\d+/g;
var string = "You have 100 seconds time to run";
var matches = string.match(regex);
console.log(matches);      

輸出是所有比對項的數組:

[100]      

例如,正規表達式可用于在大型文本檔案中搜尋電子郵件或電話号碼。

67、調試代碼時斷點的目的是什麼?

斷點允許你查找 JavaScript 代碼中的錯誤。

當執行調試器語句并出現調試器視窗時,你可以在代碼中設定斷點。

在斷點處,JavaScript 停止執行并讓你檢查值和範圍以解決可能的問題。

68、什麼是條件運算符?

條件運算符是編寫 if-else 語句的簡寫。條件運算符有時稱為三元運算符。

例如:

// Regular if-else expression:
const age = 10;
if(age < 18){
console.log("Minor");
} else {
console.log("Adult");
}
// Conditional operator shorthand for the above if-else
age < 18 ? console.log("Minor") : console.log("Adult");      

69、你能連結條件運算符嗎?

對的,這是可能的。有時它很有用,因為它可以使代碼更易于了解。

讓我們看一個例子:

function example() {
if (condition1) { return value1; }
else if (condition2) { return value2; }
else if (condition3) { return value3; }
else { return value4; }
}
// Shorthand for the above function
function example() {
return condition1 ? value1
         : condition2 ? value2
         : condition3 ? value3
         : value4;
}      

70、 freeze() 方法有什麼作用?

freeze() 方法當機一個對象。它使對象不可變。

當機對象後,無法向其添加新屬性。

例如:

const item = { name: "test" };
Object.freeze(item);
item.name = "Something else"; // Error      

71、如何擷取對象的鍵清單?

使用 Object.keys() 方法。

例如:

const student = {
  name: 'Mike',
  gender: 'male',
  age: 23
};
console.log(Object.keys(student));      

輸出:

["name", "gender", "age"]      

72、JavaScript 的原始資料類型是什麼?

原始資料類型具有原始值。JavaScript 中有七種不同的原始資料類型:

  • string——單詞。例如“約翰”。
  • number — 數值。例如12。
  • boolean — 真或假。例如真。
  • null — 沒有值。例如讓 x = null;
  • undefined — 聲明變量但沒有值的類型。例如,當以這種方式建立變量 x 時,讓 x; , x 變為未定義。
  • bigint — 表示大于 2^53-1 的整數的對象。例如 BigInt(121031393454720292)
  • symbol — 用于建立獨特符号的内置對象。例如 let sym1 = Symbol(‘test’)

73、有哪些方法可以通路對象的屬性?

共有三種通路屬性的方法。

點符号。

例如:

obj.property      

方括号表示法。

例如:

obj["property"]      

表達式符号。

例如:

obj[expression]      

74、頁面加載後如何執行JavaScript代碼?

你可以通過三種方式執行此操作:

将屬性 window.onload 設定為在頁面加載後執行的函數:

window.onload = function ...      

将屬性 document.onload 設定為在頁面加載後執行的函數:

document.onload = function ...      

将 HTML 屬性的 onload 屬性設定為 JS 函數:

<body notallow="script();">      

75、什麼是錯誤對象?

錯誤對象是一個内置對象,如果發生錯誤,它會為你提供詳細的錯誤資訊。

錯誤對象有兩個屬性:

  • name
  • message

例如,假設 sayHi() 函數抛出錯誤。發生這種情況時,catch 塊會為你提供一個錯誤對象,例如,你可以将其列印到控制台。

try {
  sayHi("Welcome");
}
catch(error) {
console.log(error.name + "\n" + error.message);
}      

76、NoScript 标簽有什麼作用?

Noscript 标簽用于檢測和響應禁用 JavaScript 的浏覽器。

你可以使用 noscript 标簽來執行一段通知使用者的代碼。

例如,你的 HTML 頁面可以有一個像這樣的 noscript 标簽:

<script>
document.write("Hello World!");
</script>
<noscript>
  Your browser does not support JavaScript!
</noscript>      

77、 什麼是入口控制循環?

在入口控制循環中,條件在進入循環體之前進行測試。

例如,for 循環和 while 循環就屬于這一類:

let nums = [1,2,3];
for (let num of nums) {
console.log(num);
}      

輸出:

1
2
3      

78、什麼是出口控制循環?

在退出控制循環中,在循環結束時評估條件。這意味着無論條件為真還是假,循環體至少執行一次。

例如,do-while 循環就屬于這一類:

const i = 0;
do {
console.log('The number is', i);
} while (i !== 0);      

輸出:

The number is 0      

79、什麼是匿名函數?

匿名函數是沒有名字的函數。

匿名函數通常配置設定給變量名稱或用作回調函數。

這是一個帶有名稱供參考的函數:

function example(params) {
// do something
}      

這是一個配置設定給變量的匿名函數:

const myFunction = function() {
// do something
};      

這是一個用作回調的匿名函數:

[1, 2, 3].map(function(element) { 
// do something
});      

80、什麼是疊代器?

疊代器協定使對象生成一系列值成為可能。

疊代器必須實作 next() 方法來擷取序列中的下一個值。此方法傳回一個對象

  • value - 疊代序列中的下一個值
  • done - 如果此值是序列中的最後一個,則為真。如果不是,那就是假的。

這是建立和使用疊代器的示例。這個函數實作了一個可以被 rangeIter(1,5) 調用的範圍疊代器,并列印值 1 2 3 4。

// define a function that returns an iterator 
function rangeIter(start = 0, end = Infinity, step = 1) {
let nextIndex = start;
let count = 0;
// create the actual iterator object
const iterator = {
// create the next() method that knows how to get the next value in the sequence
       next: function() {
let result;
if (nextIndex < end) {
// Return the value and set done 'false' because the iteration is not completed
               result = { value: nextIndex, done: false }
               nextIndex += step;
               count++;
return result;
           }
// set done 'true' when the end has been reached
return { value: count, done: true }
       }
    };
// return an iterator object
return iterator;
}
// Using the iterator
const it = rangeIter(1, 5);
let result = it.next();
while (!result.done) { // prints 1 2 3 4
console.log(result.value);
     result = it.next();
}      

81、什麼是可疊代對象?

可疊代協定意味着一個對象可以被疊代,是以實作了疊代器協定(問題 80。)

換句話說,你可以在任何可疊代對象上使用 for...of 循環來循環周遊它生成的值序列。

例如,Array 或 Map 在 JavaScript 中是可疊代的,但 Object 不是。

下面是一個在數組上應用 for...of 循環的例子,它本質上是可疊代的:

const nums = [1,2,3];
for (let num of nums) {
console.log(num);
}      

輸出:

1
2
3      

82、 什麼是生成器?

生成器是疊代器的替代品。你可以編寫具有非連續執行的疊代代碼。換句話說,可以暫停生成器函數的執行。

生成器是使用 function* 文法定義的。它們不是傳回值,而是産生值。

建立時,生成器不執行其代碼。相反,它們傳回一個 Generator 對象,它本質上是一個疊代器。當你對生成器對象調用 next() 時,它會運作代碼直到遇到 yield 語句,然後停止。

例如,這是一個與上面疊代器部分中的疊代器完全相同的生成器:

// Create a generator function that returns an iterator
function* rangeIter(start = 0, end = Infinity, step = 1) {
let count = 0;
for (let i = start; i < end; i += step) {
        count++;
yield i;
    }
return count;
}
// Create a generator object
const it = rangeIter(1, 5);
// Use the generator exactly how you'd use an iterator
let result = it.next();
while (!result.done) { // prints 1 2 3 4
console.log(result.value);
     result = it.next();
}      

rangeIter 函數比疊代器示例中的 rangeIter 更容易閱讀。然而,兩者都做完全相同的事情。

83、什麼是 for of 循環?

For...of 循環可用于在 JavaScript 中疊代可疊代對象。

例如,你可以使用 for...of 循環列印數組的内容:

const nums = [1,2,3];
for (const num of nums) {
    console.log(num);
}      

輸出:

1
2
3      

84、什麼是nodejs?

Node.js 建立在 Chrome 的 JS 運作時之上。它是一個以可擴充方式建構網絡應用程式的平台。

85、什麼是事件循環?

事件循環是一個回調函數隊列。它處理所有異步回調。

當異步函數執行時,回調函數被推入隊列。JavaScript 引擎不會在異步任務完成之前觸發事件循環。

例如,事件循環的結構可能如下所示:

while (queue.waitForMessage()) {
    queue.processNextMessage();
}      

86、什麼是一進制運算符?

一進制 運算符+用于将變量轉換為數字。

如果變量無法轉換,則轉換為 NaN(這是數字的特殊情況,是以類型仍然是數字)。

例如:

let str = "10";
let num = +str;
console.log(typeof str, typeof num);
let word = "Hello";
let n = +word;
console.log(typeof word, typeof n, n);      

輸出:

string, number
string, number, NaN      

87、如何對數組的元素進行排序?

使用 sort() 對數組的項進行排序。這不會建立新數組,而是“就地”對原始數組進行排序,即直接修改它。

let months = ["Adam", "Sam", "Jack", "Bill"];
months.sort();
console.log(months);      

輸出:

["Adam", "Bill", "Jack", "Sam"]      

88、什麼是TypeScript ?

TypeScript 是帶有類型的 JavaScript。它是由 Microsoft 建立的 JavaScript 超集。

TypeScript 在普通 JavaScript 中添加了諸如可選類型、類、async/await 等類型。

這是 TypeScript 函數的一個簡單示例:

function greet(name: string): string {
return "Hello, " + name;
}
console.log(greet("Michael"));      

89、 JavaScript 中的構造函數是什麼?

構造函數是用于建立和初始化類對象的方法。當你從一個類中執行個體化一個新對象時,它就會被執行。

例如:

class Student {
constructor() {
this.name = "Mike";
  }
}
let student = new Student();
console.log(student.name);      

輸出:

Mike      

90、什麼是ES6?

ES6 (ECMAScript 6) 是 JavaScript 程式設計語言的第六個版本。它于2015年6月釋出。

91、什麼是模闆字面量?

模闆文字允許你直接在字元串中嵌入表達式。

使用模闆文字時,不要用引号聲明字元串,而是使用反引号 (`)。

要将變量或表達式嵌入到字元串中,需要在 ${} 之間添加

例如:

console.log(`This is the ${10 * 10}th time`)      

輸出:

This is the 100th time      

92、如何在沒有第三個變量的情況下交換兩個變量?

使用解構從數組中提取值。這也可用于在沒有第三個幫助程式的情況下交換兩個變量:

let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a, b)      

輸出:

2 1      

93、什麼是 ArrayBuffer?

ArrayBuffer 是通用且固定長度的二進制資料緩沖區。

let buffer = new ArrayBuffer(16);
console.log(buffer.byteLength)      

輸出:

16      

94、什麼是原型?

所有 JavaScript 對象都從原型繼承屬性。

例如:

  • Math 對象從 Math 原型繼承屬性
  • 數組對象從數組原型繼承屬性。

原型是對象的特征。它描述了與之相關的屬性。它充當對象的藍圖。

例如,你可以通路對象的原型以向對象構造函數添加新屬性,例如:

function Fruit(name, weight) {
  this.name = name;
  this.weight = weight;
}
Fruit.prototype.description = "Yum!";      

95、什麼是箭頭函數?

箭頭函數提供了在 JavaScript 中建立函數的簡寫。

你隻能在函數表達式中使用箭頭函數。

這是正常函數和箭頭函數的比較:

// Traditional function
var sum = function(a,b){
return a + b;
}
// Arrow Function
var sum = (a,b) => a + b;      

箭頭函數是在沒有 function 關鍵字的情況下聲明的。

如果隻有一個(傳回)表達式,則不需要使用 return 關鍵字。

在上面,也缺少花括号。這僅在箭頭函數僅由一個表達式組成時才有可能。如果還有更多,則需要在箭頭後添加花括号。

96、 dir()方法有什麼用?

console.dir() 将 JavaScript 對象的屬性的互動式清單顯示為 JSON。

例如:

const student = { "name":"Mike", "id": 132123, "city": "New York"};
console.dir(student);      

在控制台中産生以下互動式清單:

100道JavaScript 面試題和答案(下)

97、如何禁用網頁上的右鍵單擊?

你可以通過從 body 元素的 oncontextmenu 屬性傳回 false 來禁用網頁上的右鍵單擊。

<body notallow="return false;">      

98、什麼是一進制函數?

一進制函數是隻接受一個參數的函數。

例如:

function greet(name){
    console.log('Hello', name);
}      

99、什麼是純函數?

純函數是一個函數,無論何時何地調用它,都傳回具有相同參數的相同結果。如果函數不依賴于狀态或程式執行期間的資料更改,則該函數是純函數。

例如,計算圓面積的函數是純函數:

function circleArea(radius) {
  return Math.PI * Math.pow(radius, 2);
}      

100、什麼是對象解構?

對象解構是一種從對象(或數組)中提取屬性的方法。

在 ES6 之前,你需要這樣做來提取對象的屬性:

const PersonDetails = {
  name: "Matty",
  age: 42,
  married: false
}


const name = PersonDetails.name;
const age = PersonDetails.age;
const married = PersonDetails.married;


console.log(name);
console.log(age);
console.log(married);      

但是從 ES6 開始,你可以通過使用對象解構用一行代碼來做到這一點:

const PersonDetails = {
  name: "Matty",
  age: 42,
  married: false
}
const {name, age, married} = PersonDetails;
console.log(name);
console.log(age);
console.log(married);      

結論

謝謝閱讀。我希望你喜歡它。

祝你面試或考試好運。

程式設計快樂!

PS:到這裡,這100道面試題就已經全部分享完畢了,希望對你有所幫助,同時也歡迎你在留言區跟我留言,告訴我,你還想學習那些方面的知識。

繼續閱讀