闭包
1. 闭包的概念
es5作用域:全局作用域 + 函数级别作用域
闭包:一个函数内部的函数叫做闭包。相当于函数内部与外界连接的桥梁。
闭包解决的问题:a 帮助函数外部读取函数级别作用域中的变量 而存在。b 变量的值始终保存在内存中。
不能滥用闭包:闭包会使函数中的变量始终保存在内存中,内存消耗大,滥用闭包会对网页性能有影响。
2. 代码
2.1 函数外部读取不到函数内部的变量
// 说明:函数外面读取不到函数级别作用域中的变量username
function getName(){
var username = "zhangsan";
}
console.log(username); // 报错:username is not defined

2.2 闭包的引出
// 说明:对于内部函数getUsername而言,username变量是全局的
function getName(){
var username = "zhangsan";
function getUsername(){
// 函数内部的函数可以读取到变量username
console.log(username);
}
getUsername(); // 函数调用
}
getName(); // 函数调用

2.3 闭包–使函数外部读取到函数内部的变量
// 说明:让外界读取到 username-- 闭包 --函数内部与外界连接的桥梁
function getName(){
var username = "zhangsan";
// getUsername函数就是闭包
return function getUsername(){
return username;
}
}
// rst中接收到的是返回的getUsername函数结构
var rst = getName();
// getUsername()调用后,把返回值username存到了username中
var username = rst();
console.log(username); // zhangsan

2.4 函数每次调用后,变量内存被释放
// 说明:函数每次调用后,num变量的内存空间都会被释放,所以下次调用还是一样的结果
function add(){
var num = 0;
num += 1;
console.log(num);
}
add(); // 1
add(); // 1
add(); // 1

2.5 闭包–可使变量始终保存在内存中
function add(){
var num = 0;
// 闭包
return function(){
return num += 1;
}
}
// 每次调用函数,num都会累加,说明num的值一直保存在内存中
var fn = add();
console.log(fn()); // 1
console.log(fn()); // 2
console.log(fn()); // 3

2.6 es5中循环问题
// 返回的函数引用的变量i并非立即执行,当push到arr中的函数执行时,i的值已经=3了
var arr = [];
function createNewArr(){
// js中的for循环执行是:var i=0;var i=1; var i=2;var i=3;
// 后赋值的覆盖先赋值的,所以最终 i = 3;
for(var i = 0; i < 3; i++){
arr.push(
function(){
return i*i;
}
);
}
return arr;
}
var rst = createNewArr(); // [f,f,f]
console.log(rst[0](),rst[1](),rst[2]()); // 9 9 9
2.7 闭包–解决循环变量问题
var arr = [];
function createNewArr(){
for(var i = 0; i < 3; i++){
arr.push(
// 闭包
function(n){
return function(){
return(n*n);
}
}(i)
);
}
console.log(arr); // [f,f,f]
return arr;
}
var rst = createNewArr();
console.log(rst[0](),rst[1](),rst[2]()); // 0 1 4
2.7 补充:es6中let关键字作用域为块级作用域({}级作用域),可以不使用闭包
// es6的let关键字是块级作用域{}级作用域,可以不使用闭包
let arr = [];
function createNewArr(){
for(let i = 0; i < 3; i++){
arr.push(
function(){
return (i*i);
}
);
}
console.log(arr); // [f,f,f]
return arr;
}
var rst = createNewArr();
console.log(rst[0](),rst[1](),rst[2]());// 0 1 4
2.8 闭包中的this
闭包中的this默认情况下指向window
var name = "lisa";
var user = {
name:"zs",
getName:function(){
return function(){
// 闭包中的this指向window
console.log(this.name);
}
}
}
var fn = user.getName();
fn(); //lisa
var nickname = "昵称";
var appUser = {
nickname:"昵称1",
getNickname:function(){
// that改变this指向
var that = this;
return function(){
console.log(that.nickname);
}
}
}
var fn1 = appUser.getNickname();
fn1(); // 昵称1
3. 给变量添加属性代替闭包

给每个tabBtn添加了index属性来保存i的值

本文详细探讨了闭包的概念、作用以及在JavaScript中的运用,包括解决循环变量问题、作用域升级和内存管理。特别强调了闭包的优缺点,并介绍了es6的新特性如何替代闭包。

968

被折叠的 条评论
为什么被折叠?



