怀着一颗忐忑的心来写这篇文章,由于今天写的是闭包,关于闭包的理解可能你们都很是理解了,也怕写的很差,误导了部分的初学者,但愿下面内容有任何写的很差的地方,欢迎你们积极的指出来,真正的进步就是你们共同进步。也可以让本身成长起来,这也是我写坚持写博客的缘由之一。chrome
好了,废话闲说,咱们进入咱们的正题:闭包浏览器
function Car () {
let wheel = 4;
function drive () {
console.log(wheel + ' wheel run');
}
return drive;
}
let drive = new Car();
drive(); // 4 wheel run
复制代码
你们确定都写过相似的代码,这段代码使用了闭包;那么到底闭包是什么?如何分析出闭包为何产生和闭包到底在哪里?缓存
闭包是由函数以及建立该函数的词法环境组合而成,闭包具有的几点要素bash
为了让你们清晰的看到,咱们借助chrome的调试工具看下闭包产生的过程。 闭包
当js执行到 let drive = new Car();代码,在执行car()时,此时的Call Stack只有全局上下文。函数
接下来执行car(); 咱们能够看到,此时的drive进入了Call Stack,而且Closure(Car) 造成了。工具
经过调试,咱们看到当函数car执行时,闭包才产生,而封闭的空间Car时闭包。性能
闭包是js中的一个重要的存在,它能让不少不可能实现成为可能,可是闭包虽好,可是也不能乱用,有的时候也会拔苗助长。ui
JS分配给浏览器的可用内存数量一般比分配给桌面应用程序的少,主要是防止js的网页所有讲系统内存耗尽。咱们要想让页面具有更好的性能就必须保证页面占用最少的内存,也就是说,咱们应该保证执行的代码只保存有用的数据,一旦数据再也不有用,咱们就该进行垃圾回收,释放内存。闭包是阻止垃圾回收的,所以变量永远存在内存中。当变量再也不被使用时,会形成内存泄漏,会影响页面的性能。spa
所以当变量对象再也不使用的时候,咱们应该将其释放掉。
function Car () {
let wheel = 4;
function drive () {
console.log(wheel + ' wheel run');
}
return drive;
}
let drive = new Car();
drive(); // 4 wheel run
drive = null; // 在drive再也不使用,将其指向对象释放
复制代码
var module = (function (window, undefined) {
let name = '王小端Coder';
function getName () {
return name;
}
return {
name,
getName
}
})(window);
console.log(module.name); // 王小端Coder
console.log(module.getName()); // 王小端Coder
复制代码
一个模块具备私有属性、私有方法和公有属性、公有方法,而闭包能很好的将模块的公有属性、方法暴露出来。return关键字将对象引用赋值给module,从而使用的闭包。
for (var i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i);
}, 1000 * i);
}
复制代码
在上面这个例子中咱们实际上想依次输出 0,1,2,3,4;而不是如今的输出5个5。下面咱们进行改造。
for (var i = 0;i < 5; i++) {
(j => {
setTimeout(() => {
console.log(j);
}, 1000 * j);
})(i)
}
复制代码
在setTimeout中应用了闭包,使其内部可以记住每次循环所在的词法做用域和做用域链。因为setTimeout中的回调函数会在当前任务队列的尾部进行执行,所以上面第一个例子中每次循环中的setTimeout回调函数记住的i的值是for循环做用域中的值,此时都是5,而第二个例子记住的i的数为setTimeout的父级做用域自执行函数中的j的值,依次为0,1,2,3,4。
var fn = function () {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return sum;
}
复制代码
这个函数是返回传递参数之和,若是每次传递参数一致。结果返回都是一致的,就会形成浪费。若是改造这个函数,提升函数的性能。
var fn = (function () {
var cache = {};
return function () {
var str = JSON.stringify(arguments);
if (cache[str]) {
return cache[str];
} else {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return cache[str] = sum;
}
}
})();
复制代码
上面的示例将计算后的结果缓存到局部变量cache当中,在调用这个函数时,先在缓存中查找,若是找不到,则进行计算,而后将结果放到缓存中并返回,若是找到了,直接返回查找到的值。
若有对闭包的理解不正确的地方欢迎你们指正。谢谢!