2024年前端面试中JavaScript的30个高频面试题之中级知识

基础知识
高级知识

13. 什么是闭包?闭包的用例有哪些?

闭包是一个功能,它允许函数捕获定义该函数的环境(或保留对作用域中变量的访问)即使在该作用域已经关闭后。

我们可以说闭包是函数和词法环境的组合,其中定义了该函数。

换句话说,闭包为函数提供了访问自己的作用域、外部函数的作用域和全局作用域的能力,允许它“记住”并继续访问这些作用域中的变量和参数。

function outerFunction() {let outerVariable = 'I am from the outer function';return innerFunction() {console.log(outerVariable); // 访问外部函数作用域中的outerVariable}}let myFunction = outerFunction();
myFunction(); // 输出:I am from the outer function

每次在函数创建时以及在另一个函数内部定义函数时都会创建闭包。

执行上下文是一个执行JavaScript代码的环境。 对于每个函数调用,都会创建一个单独的执行上下文并推送到执行堆栈中。 一旦函数执行完成,它就会从堆栈中弹出。

每个执行上下文都有一个内存空间,其中存储了其变量和函数,一旦从执行堆栈中弹出函数,JavaScript垃圾收集器就会清除所有这些内容。

在JavaScript中,只有当没有引用某个对象时,该对象才会被垃圾回收。

在上面的示例中,匿名执行上下文仍对其外部环境的内存空间中的变量有引用。 即使outerFunction()已完成(它可以访问 outerVariable 变量并在console.log(outerVariable)中使用它)。

JavaScript中的闭包有几个重要用例:

  1. 数据隐私和封装:闭包可用于创建私有数据和封装有限范围内的功能。 通过在另一个函数内定义函数,内部函数可以访问外部函数的变量,但这些变量对外部函数不可访问。 这允许创建对外不直接可访问的私有数据和方法,从而增强了数据隐私和封装。

  2. 状态维护:闭包通常用于在异步操作和事件处理中维护状态。 例如,在处理异步任务时,闭包可以捕获和保留跨多个异步操作的变量状态,确保在异步任务完成时可以访问到正确的变量。

  3. 柯里化和偏函数应用:闭包有助于函数式编程技术如柯里化和偏函数应用。 通过使用闭包捕获和记住特定参数并返回使用这些捕获参数的新函数,可以实现柯里化和偏函数应用。 这允许创建具有预设参数的特化函数,提供灵活性和可重用性。

  4. 模块模式:闭包在实现JavaScript中的模块模式中至关重要。 通过使用闭包创建私有变量并只公开必要的公共方法,开发人员可以创建模块化和组织良好的代码,防止对内部模块数据的不必要访问和修改。

  5. 回调函数:在使用回调函数时,经常使用闭包。 闭包可用于在异步操作的上下文中捕获和维护变量的状态,以确保在调用回调函数时可以访问到正确的变量。

14. 解释JavaScript中的变量提升概念。

JavaScript中的变量提升是变量和函数声明自动移至其包含作用域顶部的默认行为。 这发生在编译阶段,在实际代码执行之前。 这意味着您可以在代码中声明之前使用变量或调用函数。

使用 var声明变量时,声明会被提升到包含函数或块的顶部,并使用默认值“undefined”初始化

console.log(x); // 输出:undefined
var x = 5; 

使用 letconst 声明的变量也会被提升,但是它们有一个“暂时性死区”,在该区域中不能在声明之前被访问。

console.log(x); // 抛出错误(ReferenceError) 
let x = 5; 

函数声明也会被提升到其包含作用域的顶部。您可以在代码中声明之前调用函数。

sayHello(); // 输出:Hello, world!
function sayHello() {console.log("Hello, world!"); 
}

箭头函数、函数表达式或变量初始化不会被提升。

15. 什么是暂时性死区?

暂时性死区(TDZ)是与使用 letconst 声明变量相关的 JavaScript 概念。

当您使用 letconst 声明一个变量时,它会被提升到其包含作用域的顶部,但是与 var 不同,使用 letconst 声明的变量在 TDZ 中保持未初始化状态。

在作用域内实际声明变量之前尝试访问或使用该变量会导致 ReferenceError。这可防止在变量被适当定义之前使用它。

了解暂时性死区很重要,因为它有助于防止变量在初始化之前使用导致的相关错误。它还通过鼓励在使用之前适当声明变量来推广JavaScript编码的最佳实践。

16. 什么是原型链? 以及 Object.create() 方法?

在 JavaScript 中,每个函数和对象默认都有一个名为 prototype 的属性。

JavaScript中的每个对象都有一个原型。 原型是当前对象继承属性和方法的另一个对象。 您可以将原型视为模板或父对象。

原型链是允许对象从其他对象继承属性和方法的机制

在对象上访问某个属性或方法时,JavaScript会首先在对象本身上查找它。 如果找不到,它会在原型链上向上查找,直到找到该属性或方法。 此过程会一直持续到到达链顶部的 Object.prototype 为止。

17. Call、Apply和Bind方法的区别是什么?

Call: call()方法使用指定的this值调用函数,并以逗号分隔的值的形式传入单独的参数

const person1 = { name: 'John' };
const person2 = { name: 'Jane' };function greet(greeting) {console.log(greeting + ' ' + this.name); 
}greet.call(person1, 'Hello'); // 输出:Hello John
greet.call(person2, 'Hi'); // 输出:Hi Jane  

使用 call() 方法,一个对象可以调用另一个对象所拥有的方法。

const o1 = {name: 'ravi',getName: function(){  console.log(`Hello, ${this.name}`)}
}const o2 = {name: 'JavaScript Centric'  
}o1.getName.call(o2) // Hello, JavaScript Centric

Apply: 使用给定的 this 值调用函数,但是它使用数组的形式接受参数。 当参数的数量未知或者参数已在数组中时,Apply非常有用。

const numbers = [1, 2, 3, 4, 5];   const max = Math.max.apply(null, numbers); 
console.log(max); // 输出:5

Bind: 与调用它不同,bind() 会返回一个新函数,并允许您传入任意数量的参数。bind() 方法接受一个对象作为第一个参数,并创建一个新函数。

const module = {x: 42,getX: function() {return this.x; }  
};  const boundGetX = unboundGetX.bind(module);
console.log(boundGetX()); // 输出:42

18. 什么是lambda或箭头函数?

JavaScript中有两种类型的函数:

  1. 常规函数
  2. 箭头函数(在 ES6 中引入)

常规函数: 我们可以通过两种方式编写常规函数,即函数声明函数表达式

箭头函数或胖箭头函数:也称为 lambda 函数,是在 JavaScript(ES6)中引入的一种更简洁的函数表达式语法。 与传统的函数表达式相比,它们具有较短的语法,在创建匿名函数和使用函数式编程概念方面特别有用

这里没有声明方法,我们只能通过函数表达式来编写。

箭头函数和常规函数之间有一些区别:

  1. 语法
  2. 没有参数 (参数是类数组对象)
  3. 箭头函数没有原型对象
  4. 不能用 new 关键字调用 (不是构造函数)
  5. 没有自己的 this (call、apply 和 bind 不会按预期工作)
  6. 它不能用作生成器函数
  7. 不允许重复命名的参数

19. 什么是柯里化函数?

柯里化是函数式编程中的一种技术,它将接受多个参数的函数转换成一系列每个接收单个参数的函数。 通过组合这些柯里化的函数,可以构建更复杂的函数。

在 JavaScript 中,您可以使用闭包和返回函数来实现柯里化。

// 接收两个参数的常规函数  
function add(x, y) {return x + y;
} 
// 函数的柯里化版本  
function curryAdd(x) {return function(y) {return x + y;};
}const add5 = curryAdd(5); // 偏函数应用,创建新函数  
console.log(add5(3)); // 输出:8

柯里化在函数式编程中很有用,它可以使代码更模块化和可重用。 当您想要使用变参函数或者构建数据转换流水线时,它特别有用。

20. ES6的特性有哪些?

ES6,也称为 ECMAScript 2015,为 JavaScript 引入了许多新特性和增强功能,极大地扩展了该语言的功能。 ES6的一些关键特性包括:

  1. 箭头函数
  2. 块作用域变量
  3. 模块
  4. 模板字面量: 模板字面量允许使用反引号嵌入表达式和多行字符串,这提供了在 JavaScript 中创建复杂字符串的更方便的方法。
  5. 默认参数
  6. Rest和Spread运算符
  7. 解构赋值
  8. Promise
  9. Map、Set、WeakMap、WeakSet: ES6 引入了新的内置数据结构,如 Map 和 Set,可以更高效和专门地处理集合和键值对。
  10. 迭代器和生成器
  11. 增强的对象字面量

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/343589.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux创建文件并分配权限

linux中对文件的定义 在Linux中,文件是一个具有符号名字的一组相关联元素的有序序列。文件可以包含的内容十分广泛,操作系统和用户都可以将具有一定独立功能的一个程序模块、一组数据或一组文字命名为一个文件。文件名是数据有序序列集合(文…

Vulnhub-HACKSUDO: PROXIMACENTAURI渗透

文章目录 一、前言1、靶机ip配置2、渗透目标3、渗透概括 开始实战一、信息获取二、端口敲门三、web密码爆破四、getShell五、获取新用户六、提权 一、前言 由于在做靶机的时候,涉及到的渗透思路是非常的广泛,所以在写文章的时候都是挑重点来写&#xff0…

代码随想录 516. 最长回文子序列

题目 给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。 子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。 示例 1: 输入:s “bbbab” 输出&…

基于springboot+vue药店管理系统

摘要 药店管理系统的设计和应用在当前社会背景下具有巨大的实际意义和社会价值。随着医药行业的不断发展和社会健康水平的提高,药店作为医疗服务的一部分,其管理方式也需要不断创新与优化。该系统的研究不仅关系到单一药店的运营效率,更涉及到…

Goby 漏洞发布|用友 NC registerServlet 反序列化远程代码执行漏洞

漏洞名称:用友 NC registerServlet 反序列化远程代码执行漏洞 English Name:Yonyou NC registerServlet Deserialize Remote Code Execute Vulnerability CVSS core: 9.8 影响资产数: 21320 漏洞描述: 用友 NC Cloud 是一种商…

自旋框的使用

1. 自旋框 实例化 //实例化单精度自旋框QSpinBox* spinBox new QSpinBox(this);//实例化双精度自旋框QDoubleSpinBox* doubleSpinBox new QDoubleSpinBox(this);1.1 单精度自旋框 QSpinBox 1.1.1 单精度自旋框的基本函数 QSpinBox_QDoubleSpinBox Dialog.cpp #include "…

基于python的Hurst计算预测未来发展趋势(长时序栅格影像)

1.Hurst指数反映了时间序列长期记忆性的程度,即过去的信息对未来的影响程度。Hurst指数的取值范围为0到1之间,当Hurst指数等于0.5时,时间序列被认为是一种随机漫步,即具有随机性;当Hurst指数大于0.5时,时间…

NAND Separate Command Address (SCA) 接口数据传输解读

在采用Separate Command Address (SCA) 接口的存储产品中,DQ input burst和DQ output burst又是什么样的策略呢? DQ Input Burst: 在读取操作期间,数据以一种快速并行的方式通过DQ总线传送到控制器。在SCA接口下,虽然命令和地址信…

Vue入门六(前端路由的概念与原理|Vue-router简单使用|登录跳转案例|scoped样式)

文章目录 前要:前端路由的概念与原理1)什么是路由2)SPA与前端路由3)什么是前端路由4)前端路由的工作方式 一、Vue-router简单使用1)什么是vue-router2) vue-router 安装和配置的步骤① 安装 vue-router 包②…

500mA High Voltage Linear Charger with OVP/OCP

一、General Description YHM2810 is a highly integrated, single-cell Li-ion battery charger with system power path management for space-limited portable applications. The full charger function features Trickle-charge, constant current fast charge and const…

【DevOps-08-3】Jenkins容器内部使用Docker

一、简要描述 构建镜像和发布镜像到harbor都需要使用到docker命令。而在Jenkins容器内部安装Docker官方推荐直接采用宿主机带的Docker即可。 设置Jenkins容器使用宿主机Docker。 二、配置和操作步骤 1、修改宿主机docker.sock权限 # 修改docker.sock 用户和用户组都为root $ …

Postman进行Soap webservice接口测试

许多人认为Postman是高级REST客户端,Postman是处理通过HTTP发送的请求的工具。其实Postman也可以测试与协议无关的SOAP webservice api接口。 要使用Postman发出SOAP请求,请执行以下操作: 1、提供SOAP端点作为URL,可以使用SOAP的W…