面试前端八股文十问十答第四期
相信看了本文后,对你的面试是有一定帮助的!关注专栏后就能收到持续更新!
⭐点赞⭐收藏⭐不迷路!⭐
1)var、let 和 const 的区别:
var
是 JavaScript 中较早的变量声明关键字,它存在变量提升和函数作用域的特性。使用var
声明的变量可以被重新声明和重新赋值。let
和const
是 ES6(ECMAScript 2015)引入的新的变量声明方式。它们都具有块级作用域的特性,意味着它们在{}
内部声明的变量只在该块级作用域内有效。与var
不同,使用let
声明的变量可以被重新赋值,但不能被重新声明。而使用const
声明的变量是常量,一旦赋值就不能再改变,且不能被重新声明。
2)JavaScript 垃圾回收机制:
JavaScript 中的垃圾回收机制主要通过自动内存管理来实现。它使用的主要算法是标记-清除算法。该算法在程序中定期执行,标记那些不再需要的变量,然后清除它们释放内存。此外,JavaScript 引擎还会尽可能地减少内存泄漏的发生,通过及时释放不再需要的变量来避免内存泄漏的发生。
3)作用域和作用域链:
作用域是指变量在代码中的可访问范围。在 JavaScript 中,作用域分为全局作用域和局部作用域。函数内部声明的变量只能在该函数内部访问,这就是函数作用域。而块级作用域是在 {}
内部声明的变量,它们只在该块级作用域内有效。
作用域链是指在嵌套的作用域结构中,内部作用域可以访问外部作用域的变量,但外部作用域无法访问内部作用域的变量。当变量在作用域中被引用时,JavaScript 引擎会沿着作用域链查找变量的值。
希望这些解答对你有所帮助,如果还有其他问题,请随时提出。
4)闭包的两大作用:保存/保护
闭包是指函数和其词法环境的组合,可以访问定义时的作用域外部的变量。闭包有两个主要作用:
- 保存状态:闭包可以保存函数定义时的状态信息,使得函数在定义时的作用域外部的变量在函数调用时仍然可用,从而实现状态的持久化。
- 保护变量:闭包可以创建私有变量和方法,将其封装在闭包内部,不被外部访问,从而实现变量的保护和隐藏。
5)JavaScript 中 this 的五种情况
- 全局环境中的 this :在全局环境中,
this
指向全局对象(浏览器中通常是window
对象)。 - 函数中的 this :在函数中,
this
的值取决于函数的调用方式。如果函数是作为对象的方法调用的,this
指向调用该方法的对象。如果函数是作为普通函数调用的,则this
指向全局对象。 - 构造函数中的 this :当函数作为构造函数被调用时(使用
new
关键字),this
指向新创建的对象。 - 使用 call()、apply()、bind() 改变 this 指向 :可以使用
call()
、apply()
或bind()
方法显式地改变函数内部的this
指向。 - 箭头函数中的 this :箭头函数没有自己的
this
,它会捕获所在上下文的this
值,也就是说,在箭头函数中,this
继承自外层作用域。
6)原型 && 原型链
- 原型(Prototype):在 JavaScript 中,每个函数都有一个特殊的属性称为原型(prototype)。原型是一个对象,包含了共享给实例对象的属性和方法。当访问对象的属性或方法时,如果对象本身没有这个属性或方法,JavaScript 引擎会沿着原型链查找并返回对应的值。
- 原型链(Prototype Chain):原型链是 JavaScript 中实现继承的一种机制。当访问一个对象的属性或方法时,如果对象本身没有这个属性或方法,JavaScript 引擎会沿着原型链依次查找,直到找到对应的属性或方法,或者到达原型链的顶端(即 Object.prototype)为止。
7)new运算符的实现机制
new
运算符用于创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。它的实现机制大致如下:
- 创建一个空对象。
- 将这个空对象的原型(
__proto__
)指向构造函数的原型对象(prototype
)。 - 将构造函数的作用域赋给新对象(因此
this
指向这个新对象)。 - 执行构造函数内部的代码(为这个新对象添加属性)。
- 如果构造函数返回的是一个对象,则返回这个对象;否则返回新创建的对象。
8)EventLoop 事件循环
事件循环(Event Loop)是 JavaScript 中处理异步操作的机制,用于管理消息队列中的任务。简单来说,事件循环就是不断地从消息队列中取出消息并处理这些消息的过程。
在浏览器环境中,事件循环由浏览器的事件触发线程控制,它主要包括以下几个阶段:
- 执行同步任务:从宏任务队列中取出一个任务,执行完毕后再从微任务队列中取出一个任务执行,直到微任务队列为空。
- 执行宏任务:执行一个宏任务,执行完毕后检查微任务队列是否有任务,如果有则依次执行微任务,直到微任务队列为空。
- 进入等待:如果当前没有任务可以执行,事件循环会进入等待状态,等待新的任务被添加到消息队列中。
- 检查消息队列:当有新的任务被添加到消息队列时,事件循环会检查队列中的任务,然后继续执行上述步骤。
9)setTimeout、Promise、Async/Await 的区别
- setTimeout :
setTimeout
是一个用于在一定时间后执行函数的定时器函数。它是异步的,即在设定的时间后将回调函数推送到事件队列中执行,不会阻塞后续代码的执行。 - Promise :
Promise
是 JavaScript 提供的一种用于处理异步操作的对象,它表示一个异步操作的最终完成或失败,以及其结果值。通过Promise
,可以更方便地进行异步操作的处理,包括链式调用、错误捕获等。 - Async/Await :
Async/Await
是 ES2017 引入的异步编程解决方案,它基于Promise
,提供了更加直观、简洁的语法来处理异步操作。Async
定义一个异步函数,而Await
用于等待一个Promise
对象或者任何表达式返回的结果。
10)Async/Await 如何通过同步的方式实现异步
Async/Await
是基于 Promise
实现的,它的本质仍然是异步的,但它通过更加直观、类似同步代码的写法来处理异步操作。在语法上,Async
函数内部可以使用 Await
关键字来等待 Promise
对象的状态变化。
当我们在 Async
函数内部使用 Await
关键字时,该函数会暂停执行,直到 Await
后面的 Promise
对象状态变为 resolved
(已完成)或 rejected
(已拒绝)。在这个过程中,Async
函数会释放主线程,使得其他任务能够继续执行。一旦 Promise
对象状态变化,Async
函数会恢复执行,并返回 Promise
对象的结果。
总之,虽然 Async/Await
在语法上看起来像同步代码,但实际上它仍然是异步执行的,只是通过暂停和恢复执行的方式,使得异步代码更加易读、易维护。
开源项目地址:https://gitee.com/falle22222n-leaves/vue_-book-manage-system
前后端总计已经 900+ Star,1.5W+ 访问!
⭐点赞⭐收藏⭐不迷路!⭐