# js篇
数据类型
原始类型:number,string,bolean,undefined,null,symbol,biglnt;原始类型是存放在栈里面。
引用类型:function,Array,Object;存在堆里
衍生-栈堆概念 栈内先进后出 堆按优先级
检测数据类型的方法
typeOf:检测原始类型;
instanceOf:检测引用类型,原理是在该值的原型链中进行查找看能不能找到该类的原型;
constructor:都可以检测,缺点:如果创建的对象改了原型,constructor会判断有误;
object.prototype.toString.call():都可以检测;
衍生-原型链知识点/为什么object.prototype.tostring.call和object.tostring不一样?Array,func重写了这个方法 所以要调原型链的上面的方法。
检测数组的方法
object.protype.toString.call / instanceOf / isArray / Array.prototype.isPrototypeOf
this的指向问题
this的指向就是谁调用,指向谁。函数调用就指向那个函数,方法调用指向方法
箭头函数没有自己的this,它的this指向是上一级作用域
call,bind,apply可以改变this指向,但是改不了箭头函数的。
衍生-call,bind,apply的使用:call可以传入多个参数,apply第二个参数是数组,bind会返回个函数不会立即执行。
AMD/CommonJS/ES6 Module的区别
commonJs模块是同步的 AMD是支持异步的 CommonJS是对模块的浅拷贝 ESM是对模块的引用,只能读和存,不可以改变值
let var const
new 这个关键字做了什么
- 创建了一个空的对象
- 绑定this
- 链接到原型 A.proto=B.prototype 4.return出去
for in 和for of
for in 用来遍历对象会遍历原型链 for in 遍历对象的话 获取值 for of获取键名
数组遍历方法
forEach/map/filter/for..of/every/some/find/findIndex/reduce/reduceRight
promise.all 和 promise.race的区别
.all传入的是数组,传出也是 .race传入数组 哪个先返回就输出哪个结果
async await
async其实就是Generator的语法糖,为了优化回调地狱.then链式调用 。
async申明一个func是异步的 返回一个Promise对象 await等待一个异步方法执行完成。
垃圾回收机制
在JS运行中 不再被使用的变量 相互引用的变量 动态创建的变量 内存泄漏 都会产生垃圾 JS引擎可以自行回收内存
引用计数 创建+1 引用+1 不被引用了-1 0回收
标记清除 在内存中的变量遍历递归引用关系 每个可以访问到的变量打上标记 对于没有标记的回收
标记整理 清除后 移动变量位置 对内存压缩
V8的GC策略
分成新/老生代 新生代放存活短的 老生代放活得长的 新生代里面分两个空间FORM TO 变量先进FORM FORM满了就会进行清除回收 然后把变量复制到TO FORM清除变成了TO 后面新生代的变量经过长时间清除 还在新生代空间 就会移动到老生代
juejin.cn/post/727414…
哪些情况会导致内存泄漏
未声明的变量/被遗忘的定时器/计时器/脱离dom的引用/不合理的闭包使用
ES6 的新特性
箭头函数/解构赋值/模版字符串/promise/symbol/let const/模块化 可以通过import导入 export、export default导出/for of的循环/...拓展运算符/Map set这两种数据结构/proxy 这个方法/class 类/定义函数时候设置默认参数
事件循环
JS为了解决单个任务解决时间过长 会把任务分成同步任务 异步任务
同步任务直接执行
异步任务会放到任务队列 任务队列里面的每一个任务都是宏任务 在宏任务执行中有微任务产生的话 就添加到微任务队列里 先宏后微
宏任务 渲染/请求/script/settimeout/setinterval
微任务 .then/MutationObserver/queueMicrotask/
线程进程
当我们启动某一个程序的时候 系统会分配一块内存用来存放代码 执行任务 这块环境就叫进程
进程将任务分成很多个线程 并行处理
进程和进程直接完全隔离 互不干扰
进程里面任意一个线程崩溃 会导致该进程崩溃
当一个进程关闭的时候 系统会回收该内存
最新的Chrome浏览器包括 1个主进程 1个GPU进程 1个网络进程 多个渲染进程 多个插件进程
渲染进程中有
GUI线程 负责渲染页面 解析代码构建DOM CSSOM 渲染树和绘制页面 重排重绘也是在这个线程中进行
JS线程 负责解析JS 和GUI线程不能同时进行
计时器线程 负责setinterval 和 settimeout 的执行 如果放JS线程 阻塞了 会导致不准确
异步HTTP线程 XMLreq发出链接后的一个线程
事件触发线程 主要来控制时间循环 遇到点击 计时器 AJAX异步请求把对应任务放到时间触发线程中 触发后把时间放到待处理的队尾 等JS空下来处理
set map weekset weekmap
set类似数组 但是只能存唯一值
map类似对象 但是key和val的类型无限制
weakset weakmap 弱引用 对垃圾回收友好 不能遍历
weakset 成员只能是对象或者数组 weakMap 只能用对象作为Key
从输入URL到页面渲染发生了什么
- 判断是否是网址 不是的话用默认搜索引擎合成新的URL 有非法字符转义
- 检查缓存 先从浏览器缓存-硬盘缓存-推送缓存
- 把协议、域名、端口、路径提出来
- DNS解析 过程是客户端-浏览器缓存-本地的host-本地的DNS解析-本地的DNS服务器
- 建立TPC连接 三次握手 四次挥手 如果有https 还有TSL握手
- 响应数据 开始渲染
- DOM树 样式计算 layout布局 分层 栅格化 合成和显示
重绘和重排
重排也叫回流 改变一个元素的尺寸位置属性 会重新进行样式计算、布局 重绘 改变元素颜色 会触发重绘 重绘不会影响布局 但是会触发样式计算 重排一定触发重绘 重绘不一定触发重排 用于自己学习复习
闭包
闭包就是 在一个作用域中可以访问另一个函数内部的局部变量的函数。 看代码
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
可以发现在displayName这个作用域下访问了另外一个函数makeFunc下的局部变量name
闭包的实现,实际上是利用了JavaScript中作用域链的概念,简单理解就是:在JavaScript中,如果在某个作用域下访问某个变量的时候,如果不存在,就一直向外层寻找,直到在全局作用域下找到对应的变量为止,这里就形成了所谓的作用域链。