首页 > 其他分享 >【面试题】你理解中JS难理解的基本概念是什么?

【面试题】你理解中JS难理解的基本概念是什么?

时间:2023-10-31 11:08:01浏览次数:45  
标签:闭包 面试题 函数 作用域 JavaScript JS 队列 任务 理解


作用域与闭包

作用域

作用域是当前的执行上下文,和表达式在其中“可见”或可被访问。如果一个变量或表达式不在当前的作用域中,那么它是不可用的。作用域也可以堆叠成层次结构,子作用域可以访问父作用域,反过来则不行。————MDN

作用域最重要的特点是:子作用域可以访问父作用域,反之则不行

作用域可细分为4种:

  • 全局作用域:博爱的作用域,任何地方都能被访问到。
  • 模块作用域:一个文件的独立作用域。
  • 函数作用域:每个函数都有它的作用域。
  • 块级作用域:这是ES6引入let和const后出现的作用域。

如下,我"偷取"了You-Dont-Know-JS书里介绍作用域和闭包的示例。

【面试题】你理解中JS难理解的基本概念是什么?_事件循环

 1、2、3分别是全局作用域、函数作用域、块级作用域。也能从清晰的看出作用域的层级结构。 我相信大家肯定看过这样的面试题:

for(var i = 1;i<5;i++ ){
	setTimeout(()=>{
    console.log(i)
  },1000)
}
// 5 5 5 5 5

这种离奇的现象是怎么回事呢?且来接着来看看闭包,分说分说。

闭包

闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment词法环境)的引用的组合。换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。在 JavaScript 中,闭包会随着函数的创建而被同时创建。————MDN

哇第一眼看这个定义,会一脸懵逼。但是细细一看,其实还是一脸懵逼。让我们稍微转化一下角度,就会好理解一点。

JS中的函数创建时,它会形成闭包。拟像化理解,你养了一只小狗,小狗在出生时就跟着你,它的生活和脑海里都是你了(呜呜呜没错我是理智爱犬人士,这世界没了小狗转不了),即使它被拐卖、换主人、被你遗弃,脑海里也都是你......说到这我已经快哭了,多么感人。闭包就是这样,函数创建时,它会记住他是在哪个作用域被创建的。

举个代码例子:

function makeFunc() {
    var name = "Mozilla";
    function displayName() {
        alert(name);
    }
    return displayName;
}

var myFunc = makeFunc();
myFunc();

在本例子中,myFunc 是执行 makeFunc 时创建的 displayName 函数实例的引用。displayName 的实例维持了一个对它的词法环境(变量 name 存在于其中)的引用。因此,当 myFunc 被调用时,变量 name 仍然可用,其值 Mozilla 就被传递到alert中。————上述是MDN的解释。

现在看来是不是好理解了点,displayName就是这只小狗狗,即使被myFunc领养,也还是记住makeFunc的一切....

那么回过头来看这道面试题:

for(var i = 1;i<5;i++ ){
	setTimeout(()=>{
    console.log(i)
  },1000)
}
// 5 5 5 5 5

诶还是奇怪,为什么i只记得最后的结果,中间的过程i都没有了。思考一个问题,i在哪个作用域?i在一个for循环外面的作用域,i就一个,它在不断的做加法,多个setTimeout函数开始执行时,用的都是一个i呀。

那么该如何解决?

用let创建每个循环独有的块级作用域,它们会记住属于他们的i

for(let i = 1;i<5;i++ ){
	setTimeout(()=>{
    console.log(i)
  },1000)
}
// 1 2 3 4 5

事件循环:微任务和宏任务

浏览器中的 JavaScript 和 NodeJs 中的流程都是基于事件循环的

事件循环是 JavaScript 引擎在等待任务、执行任务俩个状态中不断循环的过程。

其中任务就分为两类:宏任务与微任务(都属于异步任务)。

宏任务

  • 渲染事件(DOM 渲染、重绘、计算布局)
  • 用户交互事件(鼠标、键盘等事件)
  • 网络请求
  • JavaScript 脚本事件

为了比较好的控制任务,页面进程引入了消息队列和事件循环机制,将要执行的宏任务依次添加到队列中,秉承着先进先出的良好品德,就这样有条不紊的按顺序执行,执行完毕就拍拍屁股滚出队列。

但是对于精确时间的把控,宏任务就难以胜任了。

DOM 事件、用户交互事件、网络请求等任务都是系统添加进队列的,我们不知道他们在队列中的次序是如何的,所以对于任务什么时候开始,我们无法掌握。

例如:

<!DOCTYPE html>
<html>
  <body>
    <div id="content">
      <li>xx</li>
    </div>
  </body>
  <script type="text/javascript">
    function timer2() {
      console.log("我来咯~");
    }
    function timer() {
      console.log('我开始咯,你来追我呀');
      setTimeout(timer2, 0);
    }
    setTimeout(timer, 0);
  </script>
</html>

示例中,JavaScript 脚本任务有俩个定时器,他们是一对很甜蜜的小情侣。我们所希望的是他们能够粘在一起,甜甜蜜蜜的。即俩个定时器执行的时机是无缝衔接的,但是 setTimeout 的执行间隔虽然可以设置成 0,实际上却是有 4ms 的间隔,所以很有可能在这间隔中就会被系统添加一些任务进入队列,打乱了队列。

宏任务的时间粒度大,使它难以胜任一些高实时性的需求。

这时候,微任务就应运而生了。

微任务

微任务的执行时机是主函数执行结束之后,当前宏函数执行结束之前。这么说大家脑海里首先浮现的是不是 Promise 的处理程序.then/.catch。

是的,它们就是典型的微任务。

宏任务有它的消息队列,微任务也有它的消息队列。当宏任务中的 JavaScript 快执行完的时候,JavaScript 引擎会查看当前微任务队列中是否有任务,如果有的话就按照顺序依次执行。

 

标签:闭包,面试题,函数,作用域,JavaScript,JS,队列,任务,理解
From: https://blog.51cto.com/u_14627797/8102459

相关文章

  • 【面试题】详解JavaScript中的Map()
    JavaScript中的Map()JavaScript是一种动态、解释性的编程语言,用于开发web上的动态页面和交互式应用程序。与其他编程语言相比,JavaScript拥有更加灵活的内置数据类型,并且拥有更高级别的调试和错误处理工具。JavaScript的核心特征之一就是其内置的Map()数据结构,本文将详细介绍JavaScr......
  • 【面试题】前端面试复习6---性能优化
    性能优化一、性能指标要在Chrome中查看性能指标,可以按照以下步骤操作:打开Chrome浏览器,并访问你想要测试的网页。使用快捷键F12或右键点击页面并选择“检查”,打开开发者工具。在开发者工具中,切换到“Performance”(性能)选项卡。点击开始录制按钮,即红色的圆点按钮。开始加载页......
  • mysql处理json格式的字段,一文搞懂mysql解析json数据
    文章目录一、概述1、什么是JSON2、MySQL的JSON3、varchar、text、json类型字段的区别二、JSON类型的创建1、建表指定2、修改字段三、JSON类型的插入1、字符串直接插入2、JSON_ARRAY()函数插入数组3、JSON_OBJECT()函数插入对象4、JSON_ARRAYAGG()和JSON_OBJECTAGG()将查询结果封装......
  • 面向Three.js开发者的3D自动纹理化开发包
    DreamTexture.js是面向three.js开发者的 3D模型纹理自动生成与设置开发包,可以为webGL应用增加3D模型的快速自动纹理化能力。图一为原始模型,图二图三为贴图后的模型。提示词:city,Realistic,cinematic,Frontview,Gamescenegraph1、DreamTexture.js开发包内......
  • 聊聊多层嵌套的json的值如何解析/替换
    前言前阵子承接了2个需求,一个数据脱敏,一个是低代码国际化多语言需求,这两个需求有个共同特点,都是以json形式返回给前端,而且都存在多层嵌套,其中数据脱敏的数据格式是比较固定,而低代码json的格式存在结构固定和不固定2种格式。最后不管是数据脱敏或者是多语言,业务抽象后,都存在需要......
  • js 中 == 和 === 区别
    在JavaScript中,==和===是用于比较值的两个不同的操作符,它们具有不同的行为:1)==(等于):它是相等操作符,用于比较两个值是否在类型转换后相等。如果两个值的内容相等,它返回true,否则返回false。类型转换是自动的,因此在比较之前,JavaScript会尝试将两个值转换为相同的类型,然后进行比较。......
  • css面试题
    1.css中的哪些单位 绝对单位:  px:像素单位 相对单位:  em:相对父元素字体大小  rem:相对根元素字体大小2.居中的方式1.水平居中1.设置盒子:margin:0auto2.display: flex2.垂直居中   1.vertical-align:middle 实现居中,1. display:i......
  • 新手使用nodejs的SerialPort获取数据时需要注意的一个小点
    onData(callback:(data:Buffer)=>void):void{if(this.serialPort!=null){this.serialPort.on("data",(data:Buffer)=>{callback(data);})}}​ 上面的代码相当于当串口接收到数据之后就通知......
  • 基于Vue.js和Vanta.js的动态天空颜色效果实现
    背景最近在写一个Vue项目,想要在登录界面加一个动态背景效果,搜索之后发现了Vanta.js(https://www.vantajs.com/)这个库。Vanta可以借助three.js(WebGL)或p5.js渲染动态的3D背景效果,提供了多种预设。几种效果都挺不错的,最终我决定采用clouds效果。随即我发现这个效果是可......
  • SocketJS使用记录
    SockJS是一个JavaScript库,用于处理WebSocket或WebSocket风格的双向通信。以下是SockJS的一些主要函数及其作用的简要介绍,并附带一些示例:newSockJS(url,[options]):创建SockJS客户端实例。url参数是WebSocket服务器的URL或端点,options是一个可选的配置对象,......