前端知识点(面试可看) —— JS
摘要
马上就要毕业啦,没有参加2023年的秋招,准备在最近开始找全职或者实习工作,然后也马上过年了,总结和理一下自己的知识要点,参加2024年的春招。
1. JS的执行流程
- 浏览器的V8引擎收到到执行的JS代码
- V8结构化这段代码,生成AST(抽象语法树),同时生成相关作用域
- 生成字节码(介于AST和机器码之间)
- 解释器,按照顺序执行字节码,并输出执行结果
JS代码流程:先编译后执行
2. 基本数据类型
- undefined
- null
- Boolean
- String
- Number
- Symbol
- BigInt
- Object:只有他存在堆里面
3. 判断数据类型的方式(TTIC)
- typeof:判断基本数据类型,判断null时,会返回
object
- Object.prototype.toString.call(xx):返回一个
[object 数据类型]
- instanceof:
A instanceof B
:判断A和B是否有血缘关系,不仅仅根据父子关系。 - constructor
4. ES6的新特性
const
和let
- 解构赋值
- 模板字符串
- 函数的扩展:默认值、rest参数、函头函数
- 数组的拓展:Array.from()将类数组转换为数组、find()、findIndex()、entries()、keys()、values(),includes()
- 对象扩展:属性名可以用表达式、Object.assign()、Object.keys()、Object.values()、Object.entries()
- Symbol
- Set、Map
- Promise
- Iterator和for…of
- Generator 和 async await
箭头函数和普通函数
- 语法更加简洁清晰
- 箭头函数没有 prototype、所以箭头函数没有
this
- 箭头函数不会创建自己的this,
会自动继承最外层的this
call | apply | bind
无法改变箭头指向- 箭头函数不能作为构造函数
- 箭头函数不绑定arguments,用rest(…)取代,来访问箭头函数列表
- 箭头函数不用用作Generator,不能使用yield关键字
5. Promise 和 async/await
Promise
Promise对象为了解决
回调地狱
而提出,不是新的语法功能,而是一种新的写法,允许将回调函数嵌套,改成链式调用
流程:
- Promise 接受一个executor(),在new的时候立刻执行
- executor()内部的异步任务被放入
宏\微任务
,等待执行 - then,收集\失败回调
- executor的
异步任务被执行
,触发resolve\reject
,从失败和成功队列中取出依次执行。
其实是设计模式中的一种观察者模式
:
- 收集依赖 (then收集)
- 触发通知 (触发resolve)
- 取出依赖执行 ( resolve执行)
async await
是对Generator(生成器)的封装,是个语法糖
*/yield
和async/await
的区别:
- async/await
自带执行器
,不需要next()
就能下一步 - async 返回的是Promise对象,而Generator返回的是
生成器对象
- await能够返回
Promise
的 reject/resolve的值
注意:无论await后面跟的什么,后面的代码都会被阻塞
和Promise区别
Promise解决了回调地狱,但是他的语法问题纵向发展形成了一个回调链,遇到复杂的业务场景,这样的语法显然是不美观的。
async await看起来简洁一些,看起来像同步代码
,其实它出现的意义就是提供异步的效果
两者其实都是非阻塞
的
6. Generator
核心: 保存上下文,函数在真正意义中没有被挂起,每一次yield
,其实都执行了一边生成器函数、在这个过程中用了一个context
存储上下文,每次执行生成器函数的时候,都可以从上一个执行结果开始执行
。
用babel编译后生成regeneratorRuntime
mark()
方法为生成器函数绑定了一系列原型wrap()
相当于给Generator
增加一个_invoke
方法
7. 迭代器
模式: 可以把有些结构称为可迭代对象,它们正式实现了Iterable
接口,可以通过迭代器消费,是按需创建的一次性对象
,每个迭代器都会关联一个可迭代对象
协议: 可迭代协议需要具备两种能力
- 支持迭代的
自我识别能力
- 创建实现
Iterator
接口的对象的能力
是一次性使用对象,用于迭代与其关联的可迭代对象
迭代器api提供一个next()
方法,这个方法会返回两个属性:
- done:是否还能取得下个值
- value:可迭代对象下一个值
默认实现了Iterable的类型
- String
- Array
- Map
- Set
- arguments
- NodeList等Dom集合类型
接受可迭代对象的原生语言特性包括
- for of
- 数组结构
- 扩展操作符
- Array.from()
- Set
- Map
- Promise.all()
- Promise.race()
- yield
8. 设计模式
三类:(C5S7B11)
- 创建型模式:五种: 工厂方法、抽象工厂、单例、建造则、原型
- **结构型模式:七种:**适配器、装饰器、代理、外观、桥接、组合、享元
- **行为型模式:十一种:**策略、模板方法、观察者(发布订阅)、迭代子、责任链、命令、备忘录、状态、访问者、中介者、模板方法、解释器
9. WebGL
Canvas
是画布一般可以获取2D上下文
和3D上下文
,3D上下文
一般就是WebGL
,当然WebGL
也能用于2D绘制,并且WebGL
提供硬件渲染加速,性能更好。但是支持性不是特别好,在不支持的情况下最好还是用Canvas
,可以用一些兜底的库,如threehs、PIXI
等
10. CommonJS和ES6 Module
首先,CommonJS
是同步加载
,ES6
是异步加载
,前者主要用于Node.js服务端编程
,模块文件一般已经存在于本地硬盘
,所以记载比较快。而后者是异步加载
所以适用于浏览器,不会造成堵塞。
其次,CommonJS
模块输出的是一个值的拷贝,也就是说一旦输出一个值,模块内部变化就影响不到这个值
,ES6
模块输出的是值的引用,V8引擎在对JS进行静态分析的时候,遇到import命令,会等到脚本真正执行时,才回到被加载模块中取值。
最后,前者是运行时加载
,后者是编译时输出接口
注意:CommonJS不适用于浏览器
11. 声明变量的方式
ES5
- var
- function
ES6
- let
- const
- import
- class
12. 函数声明
- function fn(…args) {}
- var fn = function(…args){}
- new Function(‘x’,‘y’,‘return x+y’)
13. Object/Map/WeakMap区别
Map
是ES6
提供的一种新特性,是一种键不局限于字符串的一种键值对集合
,对于Object
来说他的键只能使用字符串。
WeakMap
结构和Map
有点类似,但是有两点区别:
- 他只接受对象为键(null除外)
- 键名所指向的对象,不计入垃圾回收机制
总之,WeakMap
专用场合就是,它的键所对应的对象,可能会在将来消失,WeakMap
结构有助于防止内存泄露。
14. JS深浅复制
浅复制
- 扩展运算符
- Object.assign()
- Object,getOwnPropertyDescriptors()+Object.defineProperties()
深复制
- 通过嵌套扩展运算符
- 使用JSON
- 手动实现(FHT)
- 利用
for-in
对对象的属性进行遍历(自身属性+继承属性
) source.hasOwnProperty(i)
判断是否非继承
和可枚举
类型typoeof source[i]==='object
判断值的类型,如果是对象,递归处理
- 利用
15. 闭包
闭包
就是在JS种,根据语法作用域规则,内部函数总是可以访问到其外部函数中声明的变量,当通过调用
一个外部函数返回
一个内部函数后,即使该外部函数已经执行结束了。但是内部函数引用外部函数的变量依然保存在内存中,就把这些变量的集合成为闭包。
16. Event Loop
也就是事件循环
,会不听从微/宏任务队列中
取出对应任务的循环函数。在某种情况中,你可以把它称为一个永动机
。这些它取出的任务并将其推送到调用栈
种执行,主要有四个主要步骤:
- 执行Scirpt:用同步的方式执行
script
,直到调用栈空
才停下来。(还会执行预编译操作。如:变量提升) - 执行一个宏任务:挑选
最老
的到调用栈中执行,直到调用栈为空
- 执行所有微任务:挑选
最老
的到调用栈中执行,直到调用栈为空
。(但是,继续从微任务队列种获取最老的执行。重复) - UI渲染:然后跳到
第二步
,挑选宏任务执行。
Event Loop 单次迭代过程被称为tick。
宏任务 (Task Queue)
也被称为{回调队列| Callback queue}
,调用栈适用于跟踪
正在被执行函数,宏任务则是跟踪
将要被执行函数。
事件循环不停
的运行着,并且按照一定规则
从宏任务队列中不停的去除对象。
宏任务是一个
FIFO
,存储的宏任务会被事件循环探查
到。记得!这些人物都是阻塞
的。
微任务(Microtask Queue)
和宏任务一样,他也是FIFO
,同样会被探查
到。不同的地方是,微任务是在一个
宏任务完成后,在UI渲染之前被触发。它是专门处理ES6
中Promise回调的。
17. GC
也就是垃圾回收机制
。
如何实现(算法)
- 通过
GC Root
标记空间中活动对象
和非活动对象
V8
采用可访问性算法,来判断对象是否为活动对象
- 是将一些
GC Root
作为初始存活
的对象的集合 - 从
GC Root
出发然后遍历所有对象 - 通过遍历所得到的对象,认为该对象是否为
活动对象
- 通过遍历所得到的对象,认为该对象是否为
非活动对象
- 浏览器环境中,
GC Root
包括1.全局的window对象 2. 文档DOM树 3.存放栈上变量
- 回收
非活动对象
所占据的内存 - 内存整理
代际假说
是GC领域中的一个重要术语
两个特点:
- 大部分对象都是朝生夕死的
- 不死的对象,会获得很久
堆空间
V8会把堆
分为两个部分
- 新生代
- 存放的是生存时间短的
- 1~8M容量
- 副垃圾回收器,负责新生代的垃圾回收
- 老生代
- 存放时间久的对象
- 主垃圾回收器,负责老生代的垃圾回收
副垃圾回收器
用Scavenge
算法来处理,九十八新生代区域分为两个区域:对象区域
和空闲区域
。
当对象区域要被写满的时候,就做一次垃圾清理操作:
- 首先对对象区域的垃圾
做标记
- 然后把这些对象复制一份然后,有序的丢到空闲区域
- 然后复制结束后,两者角色互换
副垃圾回收器采用对象晋升策略:移动那些经过两次垃圾回收依然还活着的对象到老生代中
主垃圾回收器
负责老生代的垃圾回收,除了新生代晋升的,大的对象也会直接被存到老生代
中,有两个特点:
- 活得久
- 大得很
标记|清除 算法
- 标记过程:从根元素遍历,能够达到的为活动对象,没有达到的为非活动对象
- 垃圾清理过程:主回收器直接把非活动对象清除
标记 - 整理
- 标记可回收
- 清除:不是对可回收对象清理,二十让所有的活动对象向一端移动,清理掉除了这里以外的内存。
18. 内存问题
内存泄漏: 不需要的内存数据但是依然被其他对象引用着。
常见的: 函数中声明变量时没有用var、let、const
导致this指向window,直接赋值到window对象中。
19. 作用域
3大类:
- 声明式:函数作用域、module作用域
- 对象
- 全局
声明式作用域
通过var/const/let/class/module/import/function
生成,常说的ES6块级作用域和函数作用域都属于函数式作用域
全局作用域
全局对象使用两个ER管理:
- 对象ER:将变量存储在
全局对象
中,顶层作用域下,var
和function
声明的变量被绑定在对象ER中(浏览器为window
) - 声明式ER:使用内部对象来存储,顶层作用于下,
const/let/class
声明的变量被绑定在声明ER中
两者存在相同名的变量时,声明式ER
优先级更高。
20. this
this
是和上下文绑定的,主要分为三种:全局执行、函数执行、eval执行
全局
一般指向window
对象,这是this
和作用域链唯一焦点,作用域低端包含window
对象
函数
默认情况调用一个函数,他的上下文也是指向window
通过call/bind/apply设置上下文:
let bar = {
myName : " mango ",
test1 : 1
}
function foo(){
this.myName = " test "
}
foo.call(bar)
console.log(bar) // mango
console.log(myName) // not defined
this的设计缺陷
嵌套函数中,内部函数的this
不会从外层函数中继承
解决方法:
- 将this转化为作用域体系。
- 使用
ES6
中的this函数,他不会创建自己的上下文,所以取决于他的外部函数。
普通函数中的 this
默认指向全局对象 window
可以设置严格模式,函数上下文都是undefined
21. 图片懒加载
通过HTML提供的data-
属性来嵌入自定义数据。
然后利用offsetTop计算位置。当图片出现在可视区域的时候,加载图片,也就是给img标签设置src
。
22. 数组常用方法
改变原数组
- push
- pop
- shift
- unshift
- reverse
- sort
- splice
不会改变
- concat
- join
- slice
- filter
- reduce
- find
- findIndex
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!