深入理解JS | 青训营笔记

79 阅读4分钟

1. JS的基本概念

  1. 单线程
  2. 动态、弱类型
  3. 面向对象、函数式
  4. 解释类语言、JIT
  5. 安全、性能差

数据类型

对象:数组、函数...

基本类型:

  1. 字符串
  2. undefined
  3. 数字
  4. null
  5. symbol
  6. bigint
  7. 布尔

说实话,平常开发并没有接触到全部的基本类型

作用域

变量的可访问性和可见性

静态作用域,通过它能够预测代码在执行过程中如何查找标识符

作用域有全局作用域、函数作用域和块级作用域

变量提升

  1. var有变量提升
  2. let、const没有变量提升,提前访问会报错
  3. function函数可以先调用再定义
  4. 赋值给变量的函数无法提前调用

所以现在定义变量时一般不使用var,在ES6引入const和let后,用const和let定义变量显然是更好的选择,便于代码阅读,也便于之后找问题

2. JS是怎么执行的

当JS引擎解析到可执行代码片段(通常是函数调用)的时候,就会先做一些执行前的准备工作,这个准备工作,就叫做执行上下文(execution context 简称 EC),也叫执行环境。

执行上下文分为全部执行上下文、函数执行上下文和Eval执行上下文

全局执行上下文:代码开始执行时就会创建,将它压执行栈的栈底,每个生命周期只有一份

函数执行上下文:当执行一个函数时,这个函数内的代码会被编译,生成变量环境、词法环境等,当函数执行结束的时候该执行环境从栈顶弹出

创建执行上下文时做了:绑定This、创建词法环境、创建变量环境

词法环境:基于ECMAScript(简称ES)代码的词法嵌套结构来定义标识符和具体变量与函数的关联。一个词法环境由环境记录器和一个可能的引用外部词法环境的空值组成

变量环境:变量环境和词法环境的一个不同就是前者被用来存储函数声明和变量(let和const)绑定,而后者只用来存储var变量绑定

Outer:指向外部变量环境的一个指针

3. JS的进阶知识点

闭包

闭包内存不容易被回收,本质是没有被回收的对象

This

普通函数

普通函数的This指向Windows

对象调用

  1. 对象调用指向对象
  2. 先赋值再调用,看调用的地方

构造函数

  1. 创建临时对象
  2. 将this指向临时对象
  3. 执行构造函数
  4. 返回临时对象

垃圾回收

分为新生代空间和老生代空间

新生代空间(1M-8M):分为对象区域(放置活跃对象和变量)和空闲区域

回收过程:

  1. 垃圾标记
  2. 对象复制
  3. 区域反转

因为空间比较小,回收并不需要多少时间

老生代空间:父(主)垃圾回收器,空间比较大,新生代没能回收的对象会到老生代空间

回收过程与新生代回收过程基本一致,不过第三步改为了碎片整理,费时多,清理时JS是停顿的、不能执行的,因此垃圾回收是按照固定时间间隔周期性执行

事件循环

JS执行异步函数时,会扔到微任务或宏任务的队列里,从而不会阻塞运行,比如SetTimeout函数

微任务队列先于宏任务队列执行

4. 总结

  1. JS是单线程的,但是Render进程里面有多个线程
  2. JS线程和GUI线程互斥,执行大的计算任务会导致页面卡顿
  3. 基础数据类型存在栈上,复杂数据类型存在堆上
  4. const、let没有变量提升,提前使用会报错
  5. JS也有编译的过程,执行之前会生成执行上下文
  6. 一个执行上下文包括变量环境、词法环境、this
  7. 变量环境里面有一个指向外部函数执行上下文的指针,形成了作用域链
  8. 全局执行上下文只有一份
  9. this和执行上下文绑定