闭包
首先观察以下代码:
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
我们可能下意识认为代码不会成功运行,因为 makeFunc() 执行完毕, name 变量将不能再被访问。
但在JS中代码可运行,是因为JavaScript 中的函数会形成了闭包。
闭包是由函数以及声明该函数的词法环境组合而成的。该环境包含了这个闭包创建时作用域内的任何局部变量。在本例子中,myFunc 是执行 makeFunc 时创建的 displayName 函数实例的引用。displayName 的实例维持了一个对它的词法环境(变量 name 存在于其中)的引用。因此,当 myFunc 被调用时,变量 name 仍然可用,其值 Mozilla 就被传递到alert中。
简单来说,闭包本质是没有被回收的对象。
闭包缺点
闭包在处理速度和内存消耗方面对脚本性能具有负面影响。内存不会被回收容易导致内存泄漏。
This
普通函数的this指向window
而以下代码:
const name=11;
const obj={
name:’zq’,
showName(){
console.log(this.name)
}
}
obj.showName()
输出:zq
输出不是11而是zq,说明:
1. 对象调用指向对象。
2. 先赋值再调用。
改变指向对象的例子:
const name=11;
const obj={
name:’zq’,
showName(){
console.log(this.name)
}
const obj1={
name:’bytedance’,
}
}
obj.showName.apply(obj1)//使用apply call bind等都可以改变指向对象
输出:bytedance
而以下例子:
function ShowName(){
This.name=’zq’;
Console.log(this.name)
}
Const getName=new ShowName()
console.log(getName.name)
输出:
zq
zq
得出特点:在构造函数里面
1. new创建临时对象
2. 将this指向临时对象
3. 执行构造函数ShowName()
4. 返回临时对象
垃圾回收
对于堆的回收,堆可以分为两块,分别为新生代空间(1M-8M)和老生代空间.
新生代的回收机制
新生代的回收机制叫负垃圾回收器,有两个区域,分别为对象区域和空闲区域。
清理步骤:
1. 垃圾标记,标记对象区域的活跃数据。
2. 数据复制。将活跃数据复制到空闲区域。
3. 区域翻转。两个区域翻转后,清除对象区域。
老生代的回收机制
大数据直接放到老生代,在新生代经历两轮垃圾回收还存在的数据放到老生代。
老生代会标记应当被回收的空间,并在回收标记空间后整理自己,将不连续的空间碎片整合为连续的空间。
在标记空间时,JS运行是停止的。
事件循环
Func→微任务→宏任务
若宏任务创建了很多微任务,则先做这些微任务,再做接下来的宏任务。