常见的 JavaScript 面试问题和答案
已发表: 2023-01-13在你的投资组合中加入 JavaScript 会增加获得软件开发人员角色的机会。 也就是说,让我们看看常见的 JavaScript 面试问题。
JavaScript 是 Web 开发中最常用的语言之一。 现在几乎可以用它来开发任何类型的应用程序。
在进入面试问题之前,让我们看看学习 JavaScript 的优势。
JavaScript 是一种轻量级、解释型或即时编译型编程语言。 它是万维网的核心语言之一。 你知道 www 的其他两种核心语言。 如果你不这样做,你最好搜索它们。
JavaScript 主要是为网络创建的。 但它现在不仅适用于网络。 借助Node、Deno等环境,我们几乎可以在任何平台上运行它。
让我们来看看它的一些优点。
JavaScript 的优点
- 易于上手。 即使没有任何编码知识,您也可以学习它。
- 周围的大型社区。 如果您被困在任何地方,您将获得所需的所有帮助。
- 有很多使用 JavaScript 构建的库/框架,这有助于更快地开发应用程序。
- 我们可以使用 JavaScript 开发前端、后端、android、iOS 等应用程序。 我们可以用它创建几乎任何类型的应用程序。 但是,它在 Web 开发中更强大。
JavaScript 中的数据类型有哪些?
数据类型用于存储不同类型的数据。 一种编程语言与另一种编程语言的数据类型不同。 在 JavaScript 中,我们有 8 种数据类型。 让我们一一看看。
- 数字
- 细绳
- 布尔值
- 不明确的
- 无效的
- 大整数
- 象征
- 目的
除Object之外的所有数据类型都称为原始值。 而且它们是不可变的。
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 中创建对象。
我们可以使用大括号{}
创建对象。 创建对象简单快捷。
// 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 来调试 JavaScript。 VS Code 支持断点调试。 调试功能可能因您使用的 IDE 而异。 但是,大多数 IDE 都具有该功能。
如何在 HTML 文件中添加 JavaScript 代码?
我们可以使用script
标签添加 JavaScript HTML 文件。 您可以查看下面的示例。
<!DOCTYPE html> <html lang="en"> <head> <title>Geekflare</title> </head> <body> <h1>Geekflare</h1> <script> // JavaScript code goes here console.log("This is JavaScript code"); </script> </body> </html>
什么是 cookie?
Cookie 是用于存储小信息的键值对。 信息可以是任何东西。 我们可以设置cookies的过期时间,过期后会被删除。 这些被广泛用于存储用户的信息。
即使我们刷新页面,Cookie 也不会被清除,直到我们删除它们或它们过期为止。 您可以通过打开开发者工具在任何浏览器中查看任何网络应用程序/网页的 cookie。
如何读取cookie?
我们可以使用document.cookie
在 JavaScript 中读取 cookie。 它将返回我们创建的所有 cookie。
console.log("All cookies", document.cookie);
如果没有 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 中删除了到期日期并更改了值。
当您测试代码以使其正常工作时,使用到期日作为未来日期。 如果您保持相同的日期Jan 31 2023即使在Jan 31 2023之后,也不会创建 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,因为它已在代码的最后一行中删除。 这就是 min cookies 教程。
有哪些不同的 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 = "Geekflare";
如果你运行上面的代码,你不会看到任何错误。 但在大多数语言中,你会得到错误。 输出将是undefined
的,因为提升只会将声明移动到顶部,并且直到第 3 行才会对其进行初始化。
如下将var
更改为let
或const
,然后再次运行代码。
// Accessing `name` before declaring console.log(name); // Declaring and initializing the `name` const name = "Geekflare";
现在,您将收到引用错误,指出我们无法在初始化变量之前访问该变量。
ReferenceError: Cannot access 'name' before initialization
所以,这里在ES6中引入了let
和const
,在初始化之前是不能访问的,报错。 这是因为用let
或const
声明的变量将处于临时死区 (TDZ) 中,直到它被初始化的那一行。 我们无法从 TDZ 访问变量。
在 JavaScript 中柯里化
柯里化是一种将具有多个参数的函数转换为具有多个可调用对象的较少参数的技术。 有了它,我们可以将可调用的函数 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
函数,该函数将用于不同的函数以转换为 currying callables。 您可以参考 JavaScript Info 了解更多详细信息。
文档和窗口的区别
window
是浏览器中最顶层的对象。 它包含有关浏览器窗口的所有信息,如历史记录、位置、导航器等; 它在 JavaScript 中全球可用。 我们可以直接在我们的代码中使用它而无需任何导入。 我们可以在没有window的情况下访问window
对象的属性和方法window.
document
是window
对象的一部分。 网页上加载的所有 HTML 都转换为文档对象。 文档对象指的是特殊的HTMLDocument元素,它和所有的HTML元素一样,会有不同的属性和方法。
window
对象表示浏览器窗口,而document
表示在该浏览器窗口中加载的 HTML 文档。
客户端和服务器端的区别
客户端是指使用应用程序的最终用户。 服务器端是指部署应用程序的Web服务器。
在前端术语中,我们可以将用户计算机上的浏览器称为客户端,将云服务称为服务器端。
innerHTML 和 innerText 的区别
innerHTML
和innerText
都是 HTML 元素的属性。 我们可以使用这些属性更改 HTML 元素的内容。
我们可以将 HTML 字符串分配给innerHTML
一个像普通 HTML 一样呈现的属性。 检查下面的例子。
const titleEl = document.getElementById("title"); titleEl.innerHTML = '<span style="color:orange;">Geekflare</span>';
在您的 HTML 中添加一个带有 id title
的元素,并将上述脚本添加到 JavaScript 文件中。 运行代码并查看输出。 您将获得橙色的Geekflare
。 如果您检查该元素,它将位于span
标签内。 所以innerHTML
将获取 HTML 字符串并将其呈现为普通 HTML。
另一边的innerText
将采用普通字符串并按原样呈现。 它不会像innerHTML
那样呈现任何 HTML。 将上面代码中的innerHTML
更改为innerText
并检查输出。
const titleEl = document.getElementById("title"); titleEl.innerText = '<span style="color:orange;">Geekflare</span>';
现在,您将看到我们在网页上提供的确切字符串。
let 和 var 的区别
let
和var
关键字用于在 JavaScript 中创建变量。 ES6 中引入了let
关键字。
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 = "Geekflare"; var a = "Chandan"; console.log(a);
let a = "Geekflare"; let a = "Chandan"; console.log(a);
第一段代码不会抛出任何错误,值a
将更改为最新分配的值。 第二段代码将抛出错误,因为我们无法使用let
重新声明变量。
会话存储和本地存储的区别
会话存储和本地存储用于在用户的计算机上存储信息,这些信息可以在没有互联网的情况下访问。 我们可以将键值对存储在会话存储和本地存储中。 如果您提供任何其他数据类型或数据结构,键和值都将转换为字符串。
会话结束后(浏览器关闭时),会话存储将被清除。 在我们清除之前,位置存储不会被清除。
我们可以分别使用sessionStorage
和localStorage
对象访问、更新和删除会话存储和位置存储。
JavaScript 中的 NaN 是什么?
NaN
缩写为Not-a-Number 。 它表示某些东西在 JavaScript 中不是合法/有效的数字。 在某些情况下,我们会得到NaN
作为输出,例如0/0
、 undefined * 2
、 1 + undefined
、 null * 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
的原始值没有改变,即使我们在函数内部改变了它。
通过引用传递:它将数据的引用传递给函数。 因此,当我们对函数进行任何更改时,它也会更改原始数据。
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));
这是一个演示记忆的简单示例。 在这里,将两个数字相加并不是一项繁重的计算。 它只是为了演示。
什么是其余参数?
rest 参数用于收集函数中所有剩余的参数。 假设我们有一个函数,它至少接受 2 个参数,最多可以接受任意数量的参数。 由于我们没有参数的最大数量,我们可以使用rest operator收集前 2 个参数和普通变量,并使用rest 参数收集所有其他参数。
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 元素,一个在另一个里面。 一个事件发生在内部元素上。 现在,事件传播模式将决定这些事件的执行顺序。
事件冒泡:它首先在元素上运行事件处理程序,然后是它的元素,然后一直运行到最顶层的元素。 这是所有事件的默认行为。
事件捕获:我们需要在事件中指定我们需要使用这种类型的事件传播。 我们可以在添加事件监听器的时候指定。 如果我们启用了事件捕获,事件将按以下顺序执行。
- 事件从最顶层的元素开始执行,直到目标元素向下。
- 目标元素上的事件将再次执行。
- 冒泡事件传播将再次发生,直到最顶层元素启动。
我们可以通过在事件处理程序中调用event.stopPropogation
方法来停止事件传播。
JavaScript 中的 Promise 是什么?
Promise
对象用于异步操作,这些操作将在未来以成功或失败状态完成。
Promise
可以处于以下状态之一。
-
pending
操作仍在进行中。 -
fulfilled
当操作成功完成时。 我们将在成功状态下获得结果(如果有的话)。 -
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 中有两种类型的作用域。 全局范围和局部范围。
您可能也听说过函数作用域和块作用域。 它们分别是var
和let
、 const
的本地作用域。
什么是自调用函数?
自调用函数是无名函数,创建后将立即执行。 让我们看一些例子。
// 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
关键字声明的变量将具有函数作用域,而使用let
和const
声明的变量将具有块作用域。
有关这些变量范围的更多详细信息,请参阅第 17 个问题。
什么是 JavaScript 中的转义字符?
反斜杠是 JavaScript 中的转义符。 用来打印一些我们一般不能打印的特殊字符。 假设我们想在一个字符串中打印apostrophe (')
,但我们通常不能这样做,因为该字符串将在第二个撇号处结束。 在这种情况下,我们将转义字符以避免在该点结束字符串。
const message = 'Hi, I\'m Geekflare'; console.log(message);
我们可以在不使用转义字符的情况下通过将外部单撇号替换为双撇号来实现上述输出。 但这只是一个如何使用转义字符的例子。 还有其他字符我们肯定需要转义字符,如\n
、 \t
、 \\
等,
什么是 BOM 和 DOM?
浏览器对象模型 (BOM):所有浏览器都有代表当前浏览器窗口的 BOM。 它包含我们最顶层的窗口对象,用于操作浏览器窗口。
文档对象模型 (DOM):浏览器在树结构中加载 HTML 时创建 DOM。 我们可以使用 DOM API 操作 HTML 元素。
什么是屏幕对象?
屏幕对象是全局窗口对象的属性之一。 它包含呈现当前浏览器窗口的屏幕的不同属性。 一些属性是width 、 height 、 orientation 、 pixelDepth等。
结论
以上所有问题可能会有后续问题。 因此,您需要围绕上述所有问题准备概念。
您还可以探索一些常见的 Java 面试问题和答案。
快乐学习