let x = 5;
function fn() {
return function (y) {
console.log(y+ (++x));
}
}
let f = fn(6);
f(7);
fn(8)(9);
f(10);
console.log(x);
/**
* EC(G)
* x = 5; //6 7 8
* fn = 0x000000; [[scope]]:EC(G)
* f = 0x000001;
**/
let x = 5;
function fn() {
/*
* fn第一次执行 0x000000(6)
* EC(fn1)
* 作用域链:<EC(fn1),EC(G)>
* 形参赋值:--
* 代码执行:
* 创建一个函数 0x000001; [[scope]]:EC(fn1) 形参:y
* return 0x000001;
* “不被释放”
*/
/*
* fn(8) 第二次执行fn 0x000000(8)
* EC(fn2)
* 作用域链:<EC(fn2),EC(G)>
* 形参赋值:--
* 代码执行:
* 创建一个函数 0x000002; [[scope]]:EC(fn2) 形参:y
* return 0x000002;
* “临时不被释放”
*/
return function (y) {
/*
* f(7) EC(f1)
* 作用域链:<EC(f1),EC(fn1)>
* 形参赋值:y=7
* 代码执行:
* y+(++x) =>13
*/
/*
* 0x000002(9) EC(any) any代表倪明函数
* 作用域链:<EC(any),EC(fn2)>
* 形参赋值:y=9
* 代码执行:
* y+(++x) =>16
*/
/*
* f(10) 0x000001(10) EC(f2)
* 作用域链:<EC(f2),EC(fn1)>
* 形参赋值:y=10
* 代码执行:
* y+(++x) => 18
*/
console.log(y + (++x));
}
}
let f = fn(6);
f(7); // 7+(++5) = 13
fn(8)(9); // 9+ (++6) = 16
f(10); // 10 + (++7) = 18
console.log(x); //=> 8
GC:浏览器垃圾回收机制(内存释放机制)
【栈内存:EC】
全局执行上下文:在浏览器加载页面的时候形成,然后会在页面关闭的时候释放(页面刷新:先释放,重新加载后再形成)
私有上下文:函数执行会形成一个私有的上下文(let/const也会产生私有的上下文)
- 一般情况下代码执行完就会被出栈释放
如果当前上下文中的某个内容(一般是一个堆[对象/函数])被上下文以外的事物占用了,则当前上下文不能被释放
【堆内存:HEAP】
谷歌浏览器按照“是否被引用”来决定堆内存的释放还是不释放的:浏览器会定期间隔一段时间,查找所有堆内存是否被占用,被占用的不处理,但是如果没有被占用,则直接把它释放掉
我们可以基于手动赋值为null的方式结束堆内存的占用,来达到释放内存的目的
IE浏览器是根据“引用计数”方式实现垃圾回收的:每次被占用都会计数累加,相反取消引用,则计数累减,直到计数为零,则释放内存这种方式经常会出现记着记着就乱了 “内存泄漏”
- 扩展任务:javascript高级程序设计第三版,最后章节中有内存泄漏的问题,自己回去看看 ```javascript // 堆内存name: ‘erina’}不会被释放,因为被obj占用了 let obj = { name: ‘erina’ }
obj = null ; // 可以释放堆内存
<br />** 函数执行,会形成一个私有的上下文,这个私有上下文会保护里面的私有变量不受外界的干扰,我们把函数的这种“保护机制”称之为“闭包”;**但是一般情况下,执行完上下文就被释放了,所以闭包作用时间太短了,所以市面上一般都认为:“**函数执行,形成一个不被释放的上下文,一方面可以保护里面的私有变量不受外界干扰【保护】,另一方面也可以把这些私有变量值存储下来【保存】,这种方式才是闭包!**”
- 闭包机制会消耗计算机的内存(合理使用)
- 闭包的作用:保存/保护
闭包的表现形式:
- 大函数嵌套小函数,小函数中用到大函数的内容
- <br />
```javascript
function fn() {
let x = 10;
//fn执行,在私有上下文中创建了一个子函数(堆内存的地址),函数的地址返回给fn以外的f,f就占用了这个函数
// 当前形成的上下文不会被释放,形成闭包
return function () {
console.log(++x)
}
}
let f = fn();
f(); // 11
f(); // 12
f(); // 13
function fn() {
let obj = {
name: 'xxx'
};
// 在函数里面创建对象,被外面全局的obj占用,形成闭包
return obj;
}
let obj = fn();
function fn() {
let x = 0;
// window.xxx = function(){};
document.body.onclick = function () {
console.log(++x);
}
}
fn();