1、前置概念
- JavaScript - 词法作用域(
最核心概念)- 词法作用域是指函数和变量的作用域是在代码
编写时确定的,而不是在运行时确定的 定义函数时生效的变量作用域,不是调用函数时生效的变量作用域
- 词法作用域是指函数和变量的作用域是在代码
2、对闭包的理解
-
你不知道的JavaScript
- 使得函数可以 继续访问 定义时的词法作用域
-
Javascript 忍者秘籍2
- 允许 函数访问并操作函数 "外部" 的变量的函数
-
Javascript 高级程序设计4
- 有权访问 另一个函数作用域中的变量的函数
-
JavaScript 权威指南7
- JavaScript使用词法作用域:这意味着函数执行时使用的是
定义函数时生效的变量作用域,而不是调用函数时生效的变量作用域。为了实现词法作用域,JavaScript函数对象的内部状态不仅要包括函数代码,还要包括对函数定义所在作用域的引用。这种函数对象与作用域组合起来解析函数变量的机制,在计算机科学文献中被称作闭包。 - 严格来讲,所有JavaScript函数都是闭包。但由于多数函数调用与函数定义都在同一作用域内,所以闭包的存在无关紧要。闭包真正值得关注的时候,是定义函数与调用函数的作用域不同的时候。最常见的情形是一个函数返回了在它内部定义的嵌套函数
- JavaScript使用词法作用域:这意味着函数执行时使用的是
-
MDN
- 定义:
函数和对其周围状态的引用,捆绑在一起构成是闭包 - 能力:也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域
- 在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来
- 定义:
3、闭包的应用
基本使用
function Add3(){
var a = 10;
return function(){
a++;
return a;
};
};
var cc = Add3();
cc(); // 11
cc(); // 12
cc(); // 13
for循环中闭包的使用
function outer() {
var result = [];
for (var i = 0;i<10; i++){
// 外面包一层自执行函数,保留了当前循环的 i 值
result[i] = function (num) {
// 当执行内层函数的时候,为当前循环时的值
return function() {
// 使用闭包,每一个num值都是不一样的
console.info(num);
}
}(i) // 外套一层函数
}
return result
}
outer()[6]()
获取商品的价格区间
// 使用箭头函数
var between = (a, b)=> v =>{
return a>=v.price && b<=v.price;
}
let lessons = [
{title:"html",click:3,price:3},
{title:"html",click:34,price:34},
{title:"html",click:1,price:1}
];
console.log( lessons.filter(between(10,40)))
4、解决this的历史遗留问题
// 利用闭包、箭头函数、bind 等,解决上述问题
let user = {
name:"张三",
getName(){
let that = this;
return function(){
// return this.name; 指向 window
return that.name; // 指向 "张三"
}
}
}
user.getName()() // 张三
5、防止闭包内存泄露的策略
5.1 及时清理事件监听器和定时器
function setup() {
const element = document.getElementById('my-element');
const handler = () => {
console.log('Clicked!');
};
element.addEventListener('click', handler);
return () => {
// 清理事件监听器
element.removeEventListener('click', handler);
};
}
5.2 避免全局变量或模块作用域中的闭包
// 不推荐
let globalClosure;
function setupGlobalClosure() {
const localVariable = 'data';
globalClosure = () => {
console.log(localVariable);
};
}
// 推荐
function setupLocalClosure() {
const localVariable = 'data';
return () => {
console.log(localVariable);
};
}
const localClosure = setupLocalClosure();