【闭包】JS的闭包到底是什么

JS中的闭包是一个看着好像不难,但又很容易搞糊涂的东西,相信很多人都是和我一样似懂非懂,这次我们从最实用的角度来研究一下这个问题。

1.闭包是什么

根据MDN给出的定义:

函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起构成闭包(closure),也就是说,闭包可以让你从内部函数访问外部函数作用域
解释一下这里的词法环境,指的也就是我们常说的上下文。我们来看一个例子:

function init() {
    var name = "Mozilla"; // name 是一个被 init 创建的局部变量
    function displayName() { // displayName() 是内部函数,一个闭包
        alert(name); // 使用了父函数中声明的变量
    }
    displayName();
}
function getName(){
    console.log(name);
}

init()//alert("Mozilla")
getName()//name is not defined

在displayName这个函数内部,并没有name变量,但是它所处的词法环境,也就是外部函数init内部有一个name变量,因此可以在displayName中使用这个变量,这正是因为函数displayName中有对词法环境的引用。而在没有这个引用的getName中,则不能使用name变量.

再看第二个例子:闭包由函数

function makeFunc() {
    var name = "Mozilla";
    function displayName() {
        console.log(name);
    }
    return displayName;
}
var myFunc = makeFunc();
myFunc();

与上面的例子不同的是,这个makeFunc函数的返回值是一个还没有执行的函数。当我们执行myFunc时可以正常打印name的值,这说明displayName这个函数将makeFunc这个环境中的变量name带到了外部,进一步证明了displayName中含有指向自身词法环境的引用。

总结一下就是:

函数A内部有函数B,则在函数B中有对A内部环境的引用,所以在B中可以访问创建B时A中的所有变量,而在函数A外部则不可以访问A中的变量。在A中将B作为返回值,则返回的函数B以及函数B中对于A内部环境的引用构成了闭包

2.闭包用来干什么

通过上面的定义我们已经可以回答这个问题,闭包的存在可以让函数使用其外部函数中的变量。

不过听上去好像没什么用。那么闭包有什么实际价值呢?

我们知道,在传统的面向对象语言如java中,类会有自己的私有成员,在外部无法访问,但在JS中并不存在这种机制,无论是通过class定义类,或是通过构造函数定义对象,都没有私有变量一说,而通过闭包我们就可以完成私有变量的定义。

再看一个例子:

function number(){
    var num=0;
    function add(){
        num++;
    }
    function dec(){
        num--;
    }
    function val(){
        return num;
    }
    return{
        add:add,
        dec:dec,
        val:val
    }
}
var Num=number();
console.log(Num.num);//undefined
Num.val();//0
Num.add();
Num.val();//1
Num.dec();
Num.val()//0

可见,通过这种方法实现了私有变量,在外部无法访问Num的num成员,只能通过预留的函数接口对其进行操作和访问。

所以,在任何需要进行数据隐藏和封装的地方,都可以用上闭包

注意:

在前面我们说到了,内部函数中的引用,指向的时创建该函数时的词法环境,也就是说,如果在后面这个词法环境改变了,这个引用所指向的内容会与直觉不符。因此,在闭包中要避免使用后续会变化的一切变量。其中最常见的,如循环变量。
闭包对于性能有负面影响。若非需要,不要使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值