闭包js闭包javaScript闭包es5闭包

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

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的值
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值