zhcn 技术 数据管理 非公開: JavaScript 面试常见问题及解答

JavaScript 面试常见问题及解答

将 JavaScript 纳入您的作品集会增加您获得软件开发人员角色的机会。也就是说,让我们来看看一些常见的 JavaScript 面试问题。

JavaScript 是 Web 开发最常用的语言之一。目前它用于开发几乎所有类型的应用程序。

在进入面试问题之前,我们先来看看学习 JavaScript 的好处。

JavaScript
JavaScript

JavaScript 是一种轻量级、解释型或即时编译的编程语言。它是万维网的核心语言之一。你可能知道www的另外两种核心语言。如果没有,您应该搜索它。

JavaScript 主要是为网络编写的。但现在不仅仅是网络。借助Node、Deno 等环境,它几乎可以在任何平台上运行。

让我们看看一些好处。

JavaScript 的优点

  1. 很容易上手。无需任何编码知识即可学习。
  2. 周围有一个很大的社区。如果您遇到困难,您将获得所需的所有帮助。
  3. 有许多使用 JavaScript 构建的库/框架可以帮助加快应用程序开发速度。
  4. 您可以使用 JavaScript 开发前端、后端、Android、iOS 和其他应用程序。您可以使用它来创建几乎任何类型的应用程序。然而,它对于 Web 开发来说更加健壮。
JavaScript 面试常见问题及解答
JavaScript 面试常见问题及解答

JavaScript 中的数据类型是什么?

数据类型用于存储不同类型的数据。数据类型因编程语言而异。 JavaScript 有八种数据类型。让我们一一看看。

  • 数字
  • 细绳
  • 布尔值
  • 不明确的
  • 无效的
  • 大整型
  • 象征
  • 目的

Object之外的所有数据类型都称为原始值。而且它们是不变的。

JavaScript 面试常见问题及解答
JavaScript 面试常见问题及解答

什么是 JavaScript 内置方法?

JavaScript 对于每种数据类型都有不同的内置方法。您可以使用每种数据类型访问这些内置方法。让我们看一下针对不同数据类型和数据结构的一些内置方法。

  1. 数字
    • 固定
    • 到字符串
    • ……
  2. 细绳
    • 改为小写
    • 开始于
    • 在图表上
    • ……
  3. 大批
    • 筛选
    • 地图
    • 对每个
    • ……

每种数据类型都有许多内置方法。您可以找到各种数据类型和数据结构的所有内置方法的参考。

JavaScript 面试常见问题及解答
JavaScript 面试常见问题及解答

如何在 JavaScript 中创建数组?

数组是 JavaScript 中的核心数据结构之一。由于 JavaScript 是动态的,因此数组可以包含任何类型的数据。让我们看看如何在 JavaScript 中创建数组。

您可以使用方括号[]创建数组。创建对象既简单又快速

// Empty array
const arr = [];

// Array with some random values
const randomArr = [1, "One", true];

console.log(arr, randomArr);

您可以使用Array构造函数创建一个数组。在典型的项目中,很少使用构造函数来创建数组。

 // Empty array
const arr = new Array();

// Array with some random values
const randomArr = new Array(1, "One", true);

console.log(arr, randomArr);

JavaScript 数组是可变的。这意味着您可以在创建后根据需要对其进行修改。

JavaScript 面试常见问题及解答
JavaScript 面试常见问题及解答

如何在 JavaScript 中创建对象?

除了数组之外,对象是 JavaScript 中的另一个核心数据结构。对象使用键值对存储。键必须是不可变的值,但值可以是任何值。让我们看一下如何在 JavaScript 中创建对象。

您可以使用花括号{}创建对象。创建对象既简单又快捷。

 // Empty object
const object = {};

// Object with some random values
const randomObject = { 1: 2, one: "Two", true: false };

console.log(object, randomObject);

您可以使用Object构造函数创建对象。一般项目中很少有人用这个。

 // Empty object
const object = new Object();

// Object with some random values
const randomObject = new Object();
randomObject[1] = 2;
randomObject["one"] = "Two";
randomObject[true] = false;

console.log(object, randomObject);

JavaScript 对象是可变的。这意味着您可以在创建后对其进行修改,如第二个示例中所示。

如何调试 JavaScript 代码?

调试代码并不容易。而且它会因编程语言和项目的不同而有所不同。让我们看一下用于调试 JavaScript 的一些常用方法。

#1.日志记录

您可以在代码中的多个位置使用console.log语句来识别错误。如果上一行有错误,代码将停止执​​行下一行。

日志记录是一种古老的调试方法,对于小型项目非常有效。这是任何编程语言中常见的调试技术。

#2.开发者工具

JavaScript 主要用于开发 Web 应用程序。这就是为什么现在几乎所有浏览器都包含开发人员工具来帮助您调试 JavaScript 代码。

最常用的调试方法之一是在开发者工具中设置断点。断点会停止 JavaScript 执行并提供有关该点执行的所有信息。

您可以在发生错误的地方设置多个断点,以查看导致错误的原因。这是调试 JavaScript Web 应用程序的最有效方法。

#3. IDE

您可以使用 IDE 来调试 JavaScript。 VS Code 支持使用断点进行调试。调试功能可能会因您使用的 IDE 而异。然而,大多数 IDE 都具有该功能。

如何将 JavaScript 代码添加到 HTML 文件中?

您可以使用script标签添加 JavaScript HTML 文件。您可以查看下面的示例。

 <!DOCTYPE html>
<html lang="en">
  <head>
    <title></title>
  </head>
  <body>
    <h1></h1>

    <script>
      // JavaScript code goes here
      console.log("This is JavaScript code");
    </script>
  </body>
</html>

什么是cookie?

Cookie 是用于存储小块信息的键值对。任何信息都可以。 Cookie 可以有一个到期日期,并在到期日期后被删除。这些被广泛用于存储用户信息。

Cookie 不会通过刷新页面而被删除,除非您删除它们或它们过期。您可以通过打开开发者工具在任何浏览器中查看任何网络应用程序/网页的 cookie。

您可以使用document.cookie通过 JavaScript 读取 cookie。所有创建的 cookie 都将被返回。

 console.log("All cookies", document.cookie);

如果没有 cookie,则返回空字符串。

您可以通过将键值对设置为document.cookie来创建 cookie。让我们看一个例子。

 document.cookie = "one=One;";

在上述语法中, one cookie 键和One是它的值。您可以向 Cookie 添加属性,例如域、路径和到期日期。每个必须用分号 (;)分隔。所有属性都是可选的。

让我们看一个使用属性的示例。

 document.cookie = "one=One;expires=Jan 31 2023;path=/;";

在上面的代码中,我们添加了 cookie 的到期日期和路径。如果未指定到期日期,则 cookie 将在会话结束后删除。默认路径将是文件路径。到期日期必须采用 GMT 格式。

让我们看看如何创建多个 cookie。

 document.cookie = "one=One;expires=Jan 31 2023;path=/;";
document.cookie = "two=Two;expires=Jan 31 2023;path=/;";
document.cookie = "three=Three;expires=Jan 31 2023;path=/;";

如果您使用不同的键或路径设置多个 cookie,这些 cookie 不会被覆盖。如果key和path相同,则之前的cookie将被覆盖。查看下面的示例,该示例覆盖了先前设置的 cookie。

 document.cookie = "one=One;expires=Jan 31 2023;path=/;";
document.cookie = "one=Two;path=/;";

从 cookie 中删除了到期日期并更改了值。

如果您想测试代码是否正常工作,请使用将来的到期日期。如果您在 2023 年1 月31 日之后保留相同的日期 2023 年 1 月 31 日,则不会创建 cookie。

我们已经了解了如何创建和更新 cookie。让我们看看如何删除cookie。

删除 cookie 很简单。只需将 cookie 过期日期更改为过去的日期即可。检查下面的示例。

 // Creating cookies
document.cookie = "one=One;expires=Jan 31 2023;path=/;";
document.cookie = "two=Two;expires=Jan 31 2023;path=/;";
document.cookie = "three=Three;expires=Jan 31 2023;path=/;";

// Deleting the last cookie
document.cookie = "three=Three;expires=Jan 1 2023;path=/;";

找不到cookies中的最后一个cookie,因为最后一行代码删除了最后一个cookie。 min cookie 教程到此结束。

有哪些不同的 JavaScript 框架?

JavaScript 框架有很多。使用React、Vue、Angular等进行UI开发。用于服务器端开发,例如 Express、Koa 和 Nest。用于静态站点生成,例如 NextJS 和 Gatsby。用于移动应用程序开发的 React Native、Ionic 等。我们在这里介绍了一些 JavaScript 框架。您可以找到更多框架,但需要时间来探索它们。当你需要的时候检查一下。

JavaScript 中的闭包

闭包是一个捆绑到其词法范围及其父词法环境中的函数。闭包允许您访问外部范围中的数据。闭包是在创建函数时形成的。

 function outer() {
  const a = 1;
  function inner() {
    // We can access all the data from the outer function scope here
    // The data will be available even if we execute this function outside the outer function 
    // as inners' closure formed while creating it
    console.log("Accessing a inside inner", a);
  }
  return inner;
}

const innerFn = outer();
innerFn();

闭包广泛应用于 JavaScript 应用程序中。您以前可能使用过闭包,但没有意识到它是一个闭包。关于闭包还有很多东西需要学习。请确保您已经完全了解了这个概念。

JavaScript 中的提升

提升是 JavaScript 中的一个过程,其中变量、函数和类声明在代码执行之前被移动到作用域的顶部。

 // Accessing `name` before declaring
console.log(name);

// Declaring and initializing the `name`
var name = "";

当我运行上面的代码时,没有显示错误。然而,大多数语言都会给你一个错误。提升仅将声明移至顶部,直到第 3 行才对其进行初始化,因此输出为undefined

var更改为letconst如下所示,然后再次运行代码。

 // Accessing `name` before declaring
console.log(name);

// Declaring and initializing the `name`
const name = "";

现在我收到一个引用错误,指出在初始化变量之前无法访问该变量。

 ReferenceError: Cannot access 'name' before initialization

所以这里在ES6中引入了letconst ,但是正如错误所示,在初始化之前它们是不可访问的。这是因为用letconst声明的变量处于临时死区 (TDZ) 中,直到初始化它们的行为止。无法从 TDZ 访问变量。

JavaScript 中的柯里化

柯里化(Currying)是一种将具有多个参数的函数转换为具有多个可调用参数的少量参数的技术。这允许您将可调用函数 add(a, b, c, d) 转换为可调用 add(a)(b)(c)(d)。让我们看一个如何做到这一点的示例。

 function getCurryCallback(callback) {
  return function (a) {
    return function (b) {
      return function (c) {
        return function (d) {
          return callback(a, b, c, d);
        };
      };
    };
  };
}

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

const curriedAdd = getCurryCallback(add);

// Calling the curriedAdd
console.log(curriedAdd(1)(2)(3)(4));

getCurryCallback函数可以被泛化并用于将各种函数转换为柯里化可调用函数。有关详细信息,请参阅JavaScript 信息

文档和窗口的区别

window是浏览器的顶层对象。这包括有关您的浏览器窗口的所有信息,例如历史记录、位置、导航器等。通过 JavaScript 在全球范围内可用。您可以直接在代码中使用它,而无需导入它。您可以在没有 window 的情况下访问window对象的属性和方法window.

document window对象的一部分。加载到网页中的所有 HTML 都会转换为文档对象。文档对象指的是特殊的 HTMLDocument 元素。该元素与所有 HTML 元素一样,具有各种属性和方法。

window对象代表浏览器窗口, document代表加载到浏览器窗口中的 HTML 文档。

客户端和服务器端的区别

客户端是指使用应用程序的最终用户。服务器端是指部署应用程序的Web服务器。

在前端术语中,用户计算机上的浏览器可以称为客户端,云服务可以称为服务器端。

innerHTML 和 innerText 之间的区别

innerHTMLinnerText都是HTML 元素的属性。您可以使用这些属性来修改 HTML 元素的内容。

您可以将 HTML 字符串分配给innerHTML这是一个像常规 HTML 一样呈现的属性。检查下面的示例。

 const titleEl = document.getElementById("title");

titleEl.innerHTML = '<span style="color:orange;"></span>';

将一个带有 id title元素添加到您的 HTML 中,并将上述脚本添加到您的 JavaScript 文件中。运行代码并检查输出。橙子 这将是。如果您检查该元素,您会发现它位于span标记内。因此, innerHTML接受一个 HTML 字符串并将其呈现为常规 HTML。

另一侧的innerText采用常规字符串并按原样呈现。像innerHTML这样的HTML不会被渲染。将上面代码中的innerHTML更改为innerText并检查输出。

 const titleEl = document.getElementById("title");

titleEl.innerText = '<span style="color:orange;"></span>';

您现在将看到您在网页上提供的确切字符串。

let 和 var 之间的区别

letvar关键字用于在 JavaScript 中创建变量。 let关键字是在 ES6 中引入的。

let是块作用域, var是函数作用域。

 {
  let a = 2;
  console.log("Inside block", a);
}
console.log("Outside block", a);

运行上面的代码。由于它是块作用域,因此您无法访问块之外的let a ,因此您将在最后一行收到错误。现在将其更改为var并再次运行。

 {
  var a = 2;
  console.log("Inside block", a);
}
console.log("Outside block", a);

您还可以访问a外,因此不会发生错误。接下来,让我们用函数替换块。

 function sample() {
  var a = 2;
  console.log("Inside function", a);
}
sample();
console.log("Outside function", a);

由于它是函数作用域的,因此您无法从函数外部访问var a it,因此当您运行上述代码时,您将收到引用错误。

您可以使用var关键字重新声明变量,但不能使用let关键字重新声明变量。让我们看一个例子。

 var a = "";
var a = "Chandan";
console.log(a);
 let a = "";
let a = "Chandan";
console.log(a);

代码的第一部分不会抛出错误,并且值更改为分配给a值。代码的第二部分抛出错误,因为无法使用let重新声明该变量。

会话存储和本地存储的区别

会话存储和本地存储用于在用户计算机上存储无需 Internet 即可访问的信息。键值对可以存储在会话存储和本地存储中。如果指定任何其他数据类型或数据结构,键和值都会转换为字符串。

会话存储在会话结束后(当浏览器关闭时)被清除。在您清除位置存储之前,它不会被清除。

sessionStoragelocalStorage对象可分别用于访问、更新和删除会话存储和位置存储。

JavaScript 中的 NaN 是什么?

NaN缩写为Not-a-Number 。这意味着某些内容在 JavaScript 中不是有效数字。您可能会得到NaN输出,例如0/0undefined * 21 + undefinednull * undefined等。

什么是词法范围?

词法作用域是指从父级作用域访问变量。假设我们有一个具有两个内部函数的函数。最里面的函数可以访问其两个父函数的作用域变量。同样,二级函数可以访问最外层函数作用域。让我们看一个例子。

 function outermost() {
  let a = 1;
  console.log(a);
  function middle() {
    let b = 2;
    // `a` are accessible here
    console.log(a, b);
    function innermost() {
      let c = 3;
      // both `a` and `b` are accessible here
      console.log(a, b, c);
    }
    innermost();
  }
  middle();
}
outermost();

当您在代码中的任何位置访问变量时,JavaScript 使用作用域链来定位变量。首先,检查当前作用域中的变量,然后检查父作用域直至全局作用域。

什么是按值传递和按引用传递?

按值传递按引用传递是将参数传递给 JavaScript 中函数的两种方法。

按值传递:创建原始数据的副本并将其传递给函数。因此,您对函数所做的任何更改都不会影响原始数据。检查下面的示例。

 function sample(a) {
  // changing the value of `a`
  a = 5;
  console.log("Inside function", a);
}
let a = 3;
sample(a);
console.log("Outside function", a);

您可以看到,即使我们在函数内更改了a ,a 的原始值仍然保持不变。

通过引用传递:将数据的引用传递给函数。因此,您对函数所做的任何更改也会更改原始数据。

 function sample(arr) {
  // adding a new value to the array
  arr.push(3);
  console.log("Inside function", arr);
}
let arr = [1, 2];
sample(arr);
console.log("Outside function", arr);

您可以看到,当您更改函数内的arr时,它会更改原始值。

注意:所有原始数据类型均按值传递,非原始数据类型按引用传递。

什么是记忆化?

记忆化是一种将计算值存储在缓存中并在需要时使用它们而无需再次计算的技术。如果计算量很大,代码会运行得更快。虽然存在存储权衡,但与时间相比,这并不是什么大问题。

 const memo = {};
function add(a, b) {
  const key = `${a}-${b}`;

  // checking whether we computed the value already or not
  if (memo[key]) {
    console.log("Not computing again");
    return memo[key];
  }

  // adding the newly computed value to cache
  // here cache is a simple global object
  memo[key] = a + b;
  return memo[key];
}

console.log(add(1, 2));
console.log(add(2, 3));
console.log(add(1, 2));

这是一个演示记忆化的简单示例。现在,将两个数字加在一起并不是一个非常困难的计算。这仅用于演示目的。

剩下的参数是什么?

剩余参数用于收集函数中所有剩余参数。假设您有一个函数,它至少接受两个参数,并且最多可以接受任意数量的参数。由于参数数量没有最大限制,因此您可以使用常规变量收集前两个参数,并使用剩余运算符收集所有其他参数和其余参数

 function sample(a, b, ...rest) {
  console.log("Rest parameter", rest);
}

sample(1, 2, 3, 4, 5);

其余参数将是上例中最后三个参数的数组。这允许函数具有任意数量的参数。

一个函数只能有一个剩余参数。其余参数必须是参数顺序中的最后一个参数。

什么是对象分裂?

对象拆分用于从对象中访问变量并将其分配给与对象键同名的变量。让我们看一个例子。

 const object = { a: 1, b: 2, c: 3 };

// Object destructuring
const { a, b, c } = object;

// Now, a, b, c will be used as normal variables
console.log(a, b, c);

您可以在同一行上更改结构化变量中的变量,如下所示:

 const object = { a: 1, b: 2, c: 3 };

// Changing the names of `a` and `b`
const { a: changedA, b: changedB, c } = object;

// Now, changedA, changedB, c will be used as normal variables
console.log(changedA, changedB, c);

什么是数组结构?

数组结构用于从数组中访问变量并将它们分配给变量。让我们看一个例子。

 const array = [1, 2, 3];

// Array destructuring
// It's based on the index of the array
const [a, b, c] = array;

// Now, we can use a, b, c as normal variables
console.log(a, b, c);

什么是事件捕获和事件冒泡?

事件捕获事件冒泡是 HTML DOM 中事件传播的两种方法。假设您有两个 HTML 元素,一个位于另一个之中。该事件在内部元素上触发。这里,事件传播模式决定了这些事件的执行顺序。

事件冒泡:首先在元素上执行事件处理程序,然后在该元素上执行,最后直到顶部元素。这是所有事件的默认行为。

捕获事件:事件必须指定应使用这种类型的事件传播。可以在添加事件监听时指定。当启用事件捕获时,事件按以下顺序执行:

  1. 事件从顶部元素开始执行到目标元素。
  2. 目标元素的事件再次执行。
  3. 冒泡事件传播再次发生,直到顶部元素触发。

您可以通过调用事件处理程序的方法event.stopPropogation来停止事件传播。

JavaScript 的承诺是什么?

Promise对象用于将来完成并具有成功或失败状态的异步操作。

Promise可以处于以下状态之一:

  1. pending – 当操作仍在进行中时。
  2. fulfilled – 操作成功完成时。结果(如果有)是在成功状态下获得的。
  3. rejected – 如果操作未成功完成。您可以找出失败的原因(错误)。

让我们看两个成功和失败的例子。

 // Promise which will complete successfully
const successPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve({ message: "Completed successfully" });
  }, 300);
});
successPromise
  .then((data) => {
    console.log(data);
  })
  .catch((error) => {
    console.log(error);
  });

// Promise which will complete with failure state
const failurePromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(new Error("Failing the promise for testing"));
  }, 300);
});
failurePromise
  .then((data) => {
    console.log(data);
  })
  .catch((error) => {
    console.log(error);
  });

then您可以根据需要创建多个链。之前返回的数据将在下一个then回调中被接受。

描述 JavaScript 中不同类型的作用域

JavaScript 中有两种类型的作用域。全局范围局部范围

您可能还听说过函数作用域和块作用域。这些分别是varletconst的本地范围。

什么是自调用函数?

自调用函数是一个未命名的函数,在创建后立即执行。让我们看一些例子。

 // Without any parameters
(function sayHello() {
  console.log("Hello, World!");
})();

// With parameters
(function add(a, b) {
  console.log("Sum", a + b);
})(1, 2);

正如我们在示例中看到的,您还可以将参数传递给自调用函数。

什么是箭头函数?

箭头函数是语法糖,是经过一些修改的常规函数​​。这些行为类似于常见用例的常规函数​​。当您需要回调时,箭头函数非常有用。我们来看看它的语法。

 // arrow functions will return by default if it doesn't have any brackets
let add = (a, b) => a + b;

console.log(add(1, 2));

箭头函数和常规函数之间存在一些差异。

  • 箭头函数没有自己的this绑定。箭头函数内的this关键字引用其父作用域this
  • 箭头函数不能用作构造函数

什么是回调?

回调是传递给在该函数内调用的另一个函数的函数。使用回调在 JavaScript 中很常见。让我们看一个例子。

 function sample(a, b, callback) {
  const result = a + b;
  callback(result);
}

function finished(result) {
  console.log("Finished with", result);
}

sample(1, 2, finished);

当函数finished回调时传递给sample 。在执行某些操作后,将使用结果调用finished函数。回调的使用主要是在异步操作中,例如Promises、setTimeout等。

有哪些不同类型的错误?

让我们检查一下 JavaScript 错误。

ReferenceError :当您正在访问的变量不可用时,会发生此错误。

TypeError:如果错误与任何其他类型的错误都不匹配,则 JavaScript 会引发此错误。当您尝试执行与数据不兼容的操作时也会发生这种情况。

SyntaxError:当 JavaScript 语法不正确时会出现此错误。

还有其他几种类型的错误。然而,这些是 JavaScript 中常见的错误类型。

JavaScript 中变量的不同作用域是什么?

JavaScript 有两个变量作用域。使用var关键字声明的变量具有函数作用域,使用letconst声明的变量具有块作用域

有关这些变量范围的更多信息,请参阅问题 17。

JavaScript 中的转义字符是什么?

反斜杠是 JavaScript 中的转义字符。用于打印通常无法打印的特殊字符。假设您要在字符串中输出apostrophe (') 。这通常是不可能的,因为字符串以第二个撇号结尾。在这种情况下,请使用转义字符来防止字符串在该点终止。

 const message = 'Hi, I\'m ';
console.log(message);

通过用双撇号替换外部单撇号,可以在不使用转义字符的情况下实现上述输出。然而,这只是如何使用转义字符的一个示例。还有其他字符始终需要转义字符,例如\n\t\\

什么是 BOM 和 DOM?

浏览器对象模型 (BOM):每个浏览器都有一个表示当前浏览器窗口的 BOM。它包含用于操作浏览器窗口的顶级窗口对象。

文档对象模型 (DOM):当 HTML 加载到树结构中时,浏览器创建 DOM。您可以使用 DOM API 操作 HTML 元素。

什么是屏幕对象?

屏幕对象是全局窗口对象的属性之一。它包含呈现当前浏览器窗口的屏幕的各种属性。一些属性包括widthheightOrientationPixelDepth

结论

您可能对上述所有问题还有其他疑问。因此,您应该准备好有关上述所有问题的概念。

您还可以查找常见的 Java 面试问题和答案。

祝你学习愉快 🙂

将 JavaScript 纳入您的作品集会增加您获得软件开发人员角色的机会。也就是说,让我们来看看一些常见的 JavaScript 面试问题。

JavaScript 是 Web 开发最常用的语言之一。目前它用于开发几乎所有类型的应用程序。

在进入面试问题之前,我们先来看看学习 JavaScript 的好处。

JavaScript
JavaScript

JavaScript 是一种轻量级、解释型或即时编译的编程语言。它是万维网的核心语言之一。你可能知道www的另外两种核心语言。如果没有,您应该搜索它。

JavaScript 主要是为网络编写的。但现在不仅仅是网络。借助Node、Deno 等环境,它几乎可以在任何平台上运行。

让我们看看一些好处。

JavaScript 的优点

  1. 很容易上手。无需任何编码知识即可学习。
  2. 周围有一个很大的社区。如果您遇到困难,您将获得所需的所有帮助。
  3. 有许多使用 JavaScript 构建的库/框架可以帮助加快应用程序开发速度。
  4. 您可以使用 JavaScript 开发前端、后端、Android、iOS 和其他应用程序。您可以使用它来创建几乎任何类型的应用程序。然而,它对于 Web 开发来说更加健壮。
JavaScript 面试常见问题及解答
JavaScript 面试常见问题及解答

JavaScript 中的数据类型是什么?

数据类型用于存储不同类型的数据。数据类型因编程语言而异。 JavaScript 有八种数据类型。让我们一一看看。

  • 数字
  • 细绳
  • 布尔值
  • 不明确的
  • 无效的
  • 大整型
  • 象征
  • 目的

Object之外的所有数据类型都称为原始值。而且它们是不变的。

JavaScript 面试常见问题及解答
JavaScript 面试常见问题及解答

什么是 JavaScript 内置方法?

JavaScript 对于每种数据类型都有不同的内置方法。您可以使用每种数据类型访问这些内置方法。让我们看一下针对不同数据类型和数据结构的一些内置方法。

  1. 数字
    • 固定
    • 到字符串
    • ……
  2. 细绳
    • 改为小写
    • 开始于
    • 在图表上
    • ……
  3. 大批
    • 筛选
    • 地图
    • 对每个
    • ……

每种数据类型都有许多内置方法。您可以找到各种数据类型和数据结构的所有内置方法的参考。

JavaScript 面试常见问题及解答
JavaScript 面试常见问题及解答

如何在 JavaScript 中创建数组?

数组是 JavaScript 中的核心数据结构之一。由于 JavaScript 是动态的,因此数组可以包含任何类型的数据。让我们看看如何在 JavaScript 中创建数组。

您可以使用方括号[]创建数组。创建对象既简单又快速

// Empty array
const arr = [];

// Array with some random values
const randomArr = [1, "One", true];

console.log(arr, randomArr);

您可以使用Array构造函数创建一个数组。在典型的项目中,很少使用构造函数来创建数组。

 // Empty array
const arr = new Array();

// Array with some random values
const randomArr = new Array(1, "One", true);

console.log(arr, randomArr);

JavaScript 数组是可变的。这意味着您可以在创建后根据需要对其进行修改。

JavaScript 面试常见问题及解答
JavaScript 面试常见问题及解答

如何在 JavaScript 中创建对象?

除了数组之外,对象是 JavaScript 中的另一个核心数据结构。对象使用键值对存储。键必须是不可变的值,但值可以是任何值。让我们看一下如何在 JavaScript 中创建对象。

您可以使用花括号{}创建对象。创建对象既简单又快捷。

 // Empty object
const object = {};

// Object with some random values
const randomObject = { 1: 2, one: "Two", true: false };

console.log(object, randomObject);

您可以使用Object构造函数创建对象。一般项目中很少有人用这个。

 // Empty object
const object = new Object();

// Object with some random values
const randomObject = new Object();
randomObject[1] = 2;
randomObject["one"] = "Two";
randomObject[true] = false;

console.log(object, randomObject);

JavaScript 对象是可变的。这意味着您可以在创建后对其进行修改,如第二个示例中所示。

如何调试 JavaScript 代码?

调试代码并不容易。而且它会因编程语言和项目的不同而有所不同。让我们看一下用于调试 JavaScript 的一些常用方法。

#1.日志记录

您可以在代码中的多个位置使用console.log语句来识别错误。如果上一行有错误,代码将停止执​​行下一行。

日志记录是一种古老的调试方法,对于小型项目非常有效。这是任何编程语言中常见的调试技术。

#2.开发者工具

JavaScript 主要用于开发 Web 应用程序。这就是为什么现在几乎所有浏览器都包含开发人员工具来帮助您调试 JavaScript 代码。

最常用的调试方法之一是在开发者工具中设置断点。断点会停止 JavaScript 执行并提供有关该点执行的所有信息。

您可以在发生错误的地方设置多个断点,以查看导致错误的原因。这是调试 JavaScript Web 应用程序的最有效方法。

#3. IDE

您可以使用 IDE 来调试 JavaScript。 VS Code 支持使用断点进行调试。调试功能可能会因您使用的 IDE 而异。然而,大多数 IDE 都具有该功能。

如何将 JavaScript 代码添加到 HTML 文件中?

您可以使用script标签添加 JavaScript HTML 文件。您可以查看下面的示例。

 <!DOCTYPE html>
<html lang="en">
  <head>
    <title></title>
  </head>
  <body>
    <h1></h1>

    <script>
      // JavaScript code goes here
      console.log("This is JavaScript code");
    </script>
  </body>
</html>

什么是cookie?

Cookie 是用于存储小块信息的键值对。任何信息都可以。 Cookie 可以有一个到期日期,并在到期日期后被删除。这些被广泛用于存储用户信息。

Cookie 不会通过刷新页面而被删除,除非您删除它们或它们过期。您可以通过打开开发者工具在任何浏览器中查看任何网络应用程序/网页的 cookie。

您可以使用document.cookie通过 JavaScript 读取 cookie。所有创建的 cookie 都将被返回。

 console.log("All cookies", document.cookie);

如果没有 cookie,则返回空字符串。

您可以通过将键值对设置为document.cookie来创建 cookie。让我们看一个例子。

 document.cookie = "one=One;";

在上述语法中, one cookie 键和One是它的值。您可以向 Cookie 添加属性,例如域、路径和到期日期。每个必须用分号 (;)分隔。所有属性都是可选的。

让我们看一个使用属性的示例。

 document.cookie = "one=One;expires=Jan 31 2023;path=/;";

在上面的代码中,我们添加了 cookie 的到期日期和路径。如果未指定到期日期,则 cookie 将在会话结束后删除。默认路径将是文件路径。到期日期必须采用 GMT 格式。

让我们看看如何创建多个 cookie。

 document.cookie = "one=One;expires=Jan 31 2023;path=/;";
document.cookie = "two=Two;expires=Jan 31 2023;path=/;";
document.cookie = "three=Three;expires=Jan 31 2023;path=/;";

如果您使用不同的键或路径设置多个 cookie,这些 cookie 不会被覆盖。如果key和path相同,则之前的cookie将被覆盖。查看下面的示例,该示例覆盖了先前设置的 cookie。

 document.cookie = "one=One;expires=Jan 31 2023;path=/;";
document.cookie = "one=Two;path=/;";

从 cookie 中删除了到期日期并更改了值。

如果您想测试代码是否正常工作,请使用将来的到期日期。如果您在 2023 年1 月31 日之后保留相同的日期 2023 年 1 月 31 日,则不会创建 cookie。

我们已经了解了如何创建和更新 cookie。让我们看看如何删除cookie。

删除 cookie 很简单。只需将 cookie 过期日期更改为过去的日期即可。检查下面的示例。

 // Creating cookies
document.cookie = "one=One;expires=Jan 31 2023;path=/;";
document.cookie = "two=Two;expires=Jan 31 2023;path=/;";
document.cookie = "three=Three;expires=Jan 31 2023;path=/;";

// Deleting the last cookie
document.cookie = "three=Three;expires=Jan 1 2023;path=/;";

找不到cookies中的最后一个cookie,因为最后一行代码删除了最后一个cookie。 min cookie 教程到此结束。

有哪些不同的 JavaScript 框架?

JavaScript 框架有很多。使用React、Vue、Angular等进行UI开发。用于服务器端开发,例如 Express、Koa 和 Nest。用于静态站点生成,例如 NextJS 和 Gatsby。用于移动应用程序开发的 React Native、Ionic 等。我们在这里介绍了一些 JavaScript 框架。您可以找到更多框架,但需要时间来探索它们。当你需要的时候检查一下。

JavaScript 中的闭包

闭包是一个捆绑到其词法范围及其父词法环境中的函数。闭包允许您访问外部范围中的数据。闭包是在创建函数时形成的。

 function outer() {
  const a = 1;
  function inner() {
    // We can access all the data from the outer function scope here
    // The data will be available even if we execute this function outside the outer function 
    // as inners' closure formed while creating it
    console.log("Accessing a inside inner", a);
  }
  return inner;
}

const innerFn = outer();
innerFn();

闭包广泛应用于 JavaScript 应用程序中。您以前可能使用过闭包,但没有意识到它是一个闭包。关于闭包还有很多东西需要学习。请确保您已经完全了解了这个概念。

JavaScript 中的提升

提升是 JavaScript 中的一个过程,其中变量、函数和类声明在代码执行之前被移动到作用域的顶部。

 // Accessing `name` before declaring
console.log(name);

// Declaring and initializing the `name`
var name = "";

当我运行上面的代码时,没有显示错误。然而,大多数语言都会给你一个错误。提升仅将声明移至顶部,直到第 3 行才对其进行初始化,因此输出为undefined

var更改为letconst如下所示,然后再次运行代码。

 // Accessing `name` before declaring
console.log(name);

// Declaring and initializing the `name`
const name = "";

现在我收到一个引用错误,指出在初始化变量之前无法访问该变量。

 ReferenceError: Cannot access 'name' before initialization

所以这里在ES6中引入了letconst ,但是正如错误所示,在初始化之前它们是不可访问的。这是因为用letconst声明的变量处于临时死区 (TDZ) 中,直到初始化它们的行为止。无法从 TDZ 访问变量。

JavaScript 中的柯里化

柯里化(Currying)是一种将具有多个参数的函数转换为具有多个可调用参数的少量参数的技术。这允许您将可调用函数 add(a, b, c, d) 转换为可调用 add(a)(b)(c)(d)。让我们看一个如何做到这一点的示例。

 function getCurryCallback(callback) {
  return function (a) {
    return function (b) {
      return function (c) {
        return function (d) {
          return callback(a, b, c, d);
        };
      };
    };
  };
}

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

const curriedAdd = getCurryCallback(add);

// Calling the curriedAdd
console.log(curriedAdd(1)(2)(3)(4));

getCurryCallback函数可以被泛化并用于将各种函数转换为柯里化可调用函数。有关详细信息,请参阅JavaScript 信息

文档和窗口的区别

window是浏览器的顶层对象。这包括有关您的浏览器窗口的所有信息,例如历史记录、位置、导航器等。通过 JavaScript 在全球范围内可用。您可以直接在代码中使用它,而无需导入它。您可以在没有 window 的情况下访问window对象的属性和方法window.

document window对象的一部分。加载到网页中的所有 HTML 都会转换为文档对象。文档对象指的是特殊的 HTMLDocument 元素。该元素与所有 HTML 元素一样,具有各种属性和方法。

window对象代表浏览器窗口, document代表加载到浏览器窗口中的 HTML 文档。

客户端和服务器端的区别

客户端是指使用应用程序的最终用户。服务器端是指部署应用程序的Web服务器。

在前端术语中,用户计算机上的浏览器可以称为客户端,云服务可以称为服务器端。

innerHTML 和 innerText 之间的区别

innerHTMLinnerText都是HTML 元素的属性。您可以使用这些属性来修改 HTML 元素的内容。

您可以将 HTML 字符串分配给innerHTML这是一个像常规 HTML 一样呈现的属性。检查下面的示例。

 const titleEl = document.getElementById("title");

titleEl.innerHTML = '<span style="color:orange;"></span>';

将一个带有 id title元素添加到您的 HTML 中,并将上述脚本添加到您的 JavaScript 文件中。运行代码并检查输出。橙子 这将是。如果您检查该元素,您会发现它位于span标记内。因此, innerHTML接受一个 HTML 字符串并将其呈现为常规 HTML。

另一侧的innerText采用常规字符串并按原样呈现。像innerHTML这样的HTML不会被渲染。将上面代码中的innerHTML更改为innerText并检查输出。

 const titleEl = document.getElementById("title");

titleEl.innerText = '<span style="color:orange;"></span>';

您现在将看到您在网页上提供的确切字符串。

let 和 var 之间的区别

letvar关键字用于在 JavaScript 中创建变量。 let关键字是在 ES6 中引入的。

let是块作用域, var是函数作用域。

 {
  let a = 2;
  console.log("Inside block", a);
}
console.log("Outside block", a);

运行上面的代码。由于它是块作用域,因此您无法访问块之外的let a ,因此您将在最后一行收到错误。现在将其更改为var并再次运行。

 {
  var a = 2;
  console.log("Inside block", a);
}
console.log("Outside block", a);

您还可以访问a外,因此不会发生错误。接下来,让我们用函数替换块。

 function sample() {
  var a = 2;
  console.log("Inside function", a);
}
sample();
console.log("Outside function", a);

由于它是函数作用域的,因此您无法从函数外部访问var a it,因此当您运行上述代码时,您将收到引用错误。

您可以使用var关键字重新声明变量,但不能使用let关键字重新声明变量。让我们看一个例子。

 var a = "";
var a = "Chandan";
console.log(a);
 let a = "";
let a = "Chandan";
console.log(a);

代码的第一部分不会抛出错误,并且值更改为分配给a值。代码的第二部分抛出错误,因为无法使用let重新声明该变量。

会话存储和本地存储的区别

会话存储和本地存储用于在用户计算机上存储无需 Internet 即可访问的信息。键值对可以存储在会话存储和本地存储中。如果指定任何其他数据类型或数据结构,键和值都会转换为字符串。

会话存储在会话结束后(当浏览器关闭时)被清除。在您清除位置存储之前,它不会被清除。

sessionStoragelocalStorage对象可分别用于访问、更新和删除会话存储和位置存储。

JavaScript 中的 NaN 是什么?

NaN缩写为Not-a-Number 。这意味着某些内容在 JavaScript 中不是有效数字。您可能会得到NaN输出,例如0/0undefined * 21 + undefinednull * undefined等。

什么是词法范围?

词法作用域是指从父级作用域访问变量。假设我们有一个具有两个内部函数的函数。最里面的函数可以访问其两个父函数的作用域变量。同样,二级函数可以访问最外层函数作用域。让我们看一个例子。

 function outermost() {
  let a = 1;
  console.log(a);
  function middle() {
    let b = 2;
    // `a` are accessible here
    console.log(a, b);
    function innermost() {
      let c = 3;
      // both `a` and `b` are accessible here
      console.log(a, b, c);
    }
    innermost();
  }
  middle();
}
outermost();

当您在代码中的任何位置访问变量时,JavaScript 使用作用域链来定位变量。首先,检查当前作用域中的变量,然后检查父作用域直至全局作用域。

什么是按值传递和按引用传递?

按值传递按引用传递是将参数传递给 JavaScript 中函数的两种方法。

按值传递:创建原始数据的副本并将其传递给函数。因此,您对函数所做的任何更改都不会影响原始数据。检查下面的示例。

 function sample(a) {
  // changing the value of `a`
  a = 5;
  console.log("Inside function", a);
}
let a = 3;
sample(a);
console.log("Outside function", a);

您可以看到,即使我们在函数内更改了a ,a 的原始值仍然保持不变。

通过引用传递:将数据的引用传递给函数。因此,您对函数所做的任何更改也会更改原始数据。

 function sample(arr) {
  // adding a new value to the array
  arr.push(3);
  console.log("Inside function", arr);
}
let arr = [1, 2];
sample(arr);
console.log("Outside function", arr);

您可以看到,当您更改函数内的arr时,它会更改原始值。

注意:所有原始数据类型均按值传递,非原始数据类型按引用传递。

什么是记忆化?

记忆化是一种将计算值存储在缓存中并在需要时使用它们而无需再次计算的技术。如果计算量很大,代码会运行得更快。虽然存在存储权衡,但与时间相比,这并不是什么大问题。

 const memo = {};
function add(a, b) {
  const key = `${a}-${b}`;

  // checking whether we computed the value already or not
  if (memo[key]) {
    console.log("Not computing again");
    return memo[key];
  }

  // adding the newly computed value to cache
  // here cache is a simple global object
  memo[key] = a + b;
  return memo[key];
}

console.log(add(1, 2));
console.log(add(2, 3));
console.log(add(1, 2));

这是一个演示记忆化的简单示例。现在,将两个数字加在一起并不是一个非常困难的计算。这仅用于演示目的。

剩下的参数是什么?

剩余参数用于收集函数中所有剩余参数。假设您有一个函数,它至少接受两个参数,并且最多可以接受任意数量的参数。由于参数数量没有最大限制,因此您可以使用常规变量收集前两个参数,并使用剩余运算符收集所有其他参数和其余参数

 function sample(a, b, ...rest) {
  console.log("Rest parameter", rest);
}

sample(1, 2, 3, 4, 5);

其余参数将是上例中最后三个参数的数组。这允许函数具有任意数量的参数。

一个函数只能有一个剩余参数。其余参数必须是参数顺序中的最后一个参数。

什么是对象分裂?

对象拆分用于从对象中访问变量并将其分配给与对象键同名的变量。让我们看一个例子。

 const object = { a: 1, b: 2, c: 3 };

// Object destructuring
const { a, b, c } = object;

// Now, a, b, c will be used as normal variables
console.log(a, b, c);

您可以在同一行上更改结构化变量中的变量,如下所示:

 const object = { a: 1, b: 2, c: 3 };

// Changing the names of `a` and `b`
const { a: changedA, b: changedB, c } = object;

// Now, changedA, changedB, c will be used as normal variables
console.log(changedA, changedB, c);

什么是数组结构?

数组结构用于从数组中访问变量并将它们分配给变量。让我们看一个例子。

 const array = [1, 2, 3];

// Array destructuring
// It's based on the index of the array
const [a, b, c] = array;

// Now, we can use a, b, c as normal variables
console.log(a, b, c);

什么是事件捕获和事件冒泡?

事件捕获事件冒泡是 HTML DOM 中事件传播的两种方法。假设您有两个 HTML 元素,一个位于另一个之中。该事件在内部元素上触发。这里,事件传播模式决定了这些事件的执行顺序。

事件冒泡:首先在元素上执行事件处理程序,然后在该元素上执行,最后直到顶部元素。这是所有事件的默认行为。

捕获事件:事件必须指定应使用这种类型的事件传播。可以在添加事件监听时指定。当启用事件捕获时,事件按以下顺序执行:

  1. 事件从顶部元素开始执行到目标元素。
  2. 目标元素的事件再次执行。
  3. 冒泡事件传播再次发生,直到顶部元素触发。

您可以通过调用事件处理程序的方法event.stopPropogation来停止事件传播。

JavaScript 的承诺是什么?

Promise对象用于将来完成并具有成功或失败状态的异步操作。

Promise可以处于以下状态之一:

  1. pending – 当操作仍在进行中时。
  2. fulfilled – 操作成功完成时。结果(如果有)是在成功状态下获得的。
  3. rejected – 如果操作未成功完成。您可以找出失败的原因(错误)。

让我们看两个成功和失败的例子。

 // Promise which will complete successfully
const successPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve({ message: "Completed successfully" });
  }, 300);
});
successPromise
  .then((data) => {
    console.log(data);
  })
  .catch((error) => {
    console.log(error);
  });

// Promise which will complete with failure state
const failurePromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(new Error("Failing the promise for testing"));
  }, 300);
});
failurePromise
  .then((data) => {
    console.log(data);
  })
  .catch((error) => {
    console.log(error);
  });

then您可以根据需要创建多个链。之前返回的数据将在下一个then回调中被接受。

描述 JavaScript 中不同类型的作用域

JavaScript 中有两种类型的作用域。全局范围局部范围

您可能还听说过函数作用域和块作用域。这些分别是varletconst的本地范围。

什么是自调用函数?

自调用函数是一个未命名的函数,在创建后立即执行。让我们看一些例子。

 // Without any parameters
(function sayHello() {
  console.log("Hello, World!");
})();

// With parameters
(function add(a, b) {
  console.log("Sum", a + b);
})(1, 2);

正如我们在示例中看到的,您还可以将参数传递给自调用函数。

什么是箭头函数?

箭头函数是语法糖,是经过一些修改的常规函数​​。这些行为类似于常见用例的常规函数​​。当您需要回调时,箭头函数非常有用。我们来看看它的语法。

 // arrow functions will return by default if it doesn't have any brackets
let add = (a, b) => a + b;

console.log(add(1, 2));

箭头函数和常规函数之间存在一些差异。

  • 箭头函数没有自己的this绑定。箭头函数内的this关键字引用其父作用域this
  • 箭头函数不能用作构造函数

什么是回调?

回调是传递给在该函数内调用的另一个函数的函数。使用回调在 JavaScript 中很常见。让我们看一个例子。

 function sample(a, b, callback) {
  const result = a + b;
  callback(result);
}

function finished(result) {
  console.log("Finished with", result);
}

sample(1, 2, finished);

当函数finished回调时传递给sample 。在执行某些操作后,将使用结果调用finished函数。回调的使用主要是在异步操作中,例如Promises、setTimeout等。

有哪些不同类型的错误?

让我们检查一下 JavaScript 错误。

ReferenceError :当您正在访问的变量不可用时,会发生此错误。

TypeError:如果错误与任何其他类型的错误都不匹配,则 JavaScript 会引发此错误。当您尝试执行与数据不兼容的操作时也会发生这种情况。

SyntaxError:当 JavaScript 语法不正确时会出现此错误。

还有其他几种类型的错误。然而,这些是 JavaScript 中常见的错误类型。

JavaScript 中变量的不同作用域是什么?

JavaScript 有两个变量作用域。使用var关键字声明的变量具有函数作用域,使用letconst声明的变量具有块作用域

有关这些变量范围的更多信息,请参阅问题 17。

JavaScript 中的转义字符是什么?

反斜杠是 JavaScript 中的转义字符。用于打印通常无法打印的特殊字符。假设您要在字符串中输出apostrophe (') 。这通常是不可能的,因为字符串以第二个撇号结尾。在这种情况下,请使用转义字符来防止字符串在该点终止。

 const message = 'Hi, I\'m ';
console.log(message);

通过用双撇号替换外部单撇号,可以在不使用转义字符的情况下实现上述输出。然而,这只是如何使用转义字符的一个示例。还有其他字符始终需要转义字符,例如\n\t\\

什么是 BOM 和 DOM?

浏览器对象模型 (BOM):每个浏览器都有一个表示当前浏览器窗口的 BOM。它包含用于操作浏览器窗口的顶级窗口对象。

文档对象模型 (DOM):当 HTML 加载到树结构中时,浏览器创建 DOM。您可以使用 DOM API 操作 HTML 元素。

什么是屏幕对象?

屏幕对象是全局窗口对象的属性之一。它包含呈现当前浏览器窗口的屏幕的各种属性。一些属性包括widthheightOrientationPixelDepth

结论

您可能对上述所有问题还有其他疑问。因此,您应该准备好有关上述所有问题的概念。

您还可以查找常见的 Java 面试问题和答案。

祝你学习愉快 🙂