100 道 JavaScript 面试题及答案汇总(上)

前端达人

共 12889字,需浏览 26分钟

 · 2021-10-09


英文 | 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();

输出:

123

这是有效的,因为存储内部函数 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 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 执行相同操作的方法:

// 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、为什么需要网络存储?

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 的流程图,它也说明了如何链接它们:

25、为什么要使用承诺?

在 JavaScript 中,promise 对异步操作很有用。

过去,必须使用回调来处理异步操作,即在操作完成后立即执行的函数。这导致了“回调地狱”,一种带有嵌套回调的金字塔形代码。

Promises 通过减少回调地狱和编写更干净的代码为回调提供了另一种方法。这是可能的,因为 Promise 可以按以下方式链接:

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道题目放在下篇里,敬请继续关注。



学习更多技能

请点击下方公众号


浏览 22
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报