闭包
闭包是作用域使用的特殊情况,
我们把函数执行形成私有上下文,来保护和保存私有变量机制称为闭包。
1、是一个函数,2、可以访问其他作用域中的变量;
有两种表现
返回一个函数
function create () {
let a = 200;
return function () {
console.log(a); // 200
}
}
let a = 100
let fn = create();
fn();
作为参数被传递 ```javascript function create(fn) { let a = 100; fn(); }
let a = 200; function fn() { console.log(a); // 200,不是100 } create(fn)
可以看到,**(所有)自由变量的查找,是在函数定义的地方,向上级作用域查找,不是在执行的地方**
<a name="OMg70"></a>
## 应用
1. 模仿块级作用域
2. 保护外部函数的变量 能够访问函数定义时所在的词法作用域(阻止其被回收)
3. 封装私有化变量
4. 创建模块
<a name="cGCDh"></a>
### 隐藏数据
```javascript
let createCache = function () {
let data = {};
return {
get: function (key) {
return data[key];
},
set: function (key, value) {
data[key] = value;
return data;
}
}
}
let cache = createCache();
cache.set('token', 'token');
cache.get('token');
节流和防抖的使用
- 节流
以一个固定的间隔去触发,用于稀疏函数的执行频率
// 节流
let throttle = function (fn, delay) {
let prev = 0;
return function () {
let self = this;
let argus = arguments;
let now = Date.now();
if (now - prev > delay) {
fn.apply(self, argus);
prev = now;
}
}
}
- 防抖
频繁触发,只执行最后一次
// 防抖
let debounce = function (fn, delay) {
let timeout = null;
return function () {
let self = this;
let argus = arguments;
if (timeout) clearTimeout(timeout);
timeout = setTimeout(function () {
fn.apply(self, argus);
}, delay);
}
}
实现bind函数
// 模拟bind的实现
Function.prototype.bind1 = function () {
// 将参数拆解为数组
const args = Array.prototype.slice.call(arguments);
// 获取this,并从数组剔除
const _this = args.shift();
// 原来的fn,fn.bind(...)的fn1
const self = this;
// 返回一个函数
return function () {
return self.apply(_this, args);
}
};
function fn () {
console.log(this);
console.log(arguments);
return 'this is a fn';
}
let fn1 = fn.bind1({
name: 'fn',
}, 10, 20);
fn1();
缺点
变量会常驻内存,可能造成内存泄露
因为内存得不到及时的释放,可以人为的去置为null
js垃圾回收机制
- �标记使用法
当这个函数结束,变量不再使用就得到了释放;
- 引用计数法
在一定时间内不再使用;