【javascript基础】由demo来进阶学习闭包等概念

本文深入浅出地介绍了JavaScript中的闭包概念,包括闭包的基本定义、特性及其应用场景。通过具体的代码示例,展示了如何利用闭包来模拟私有变量和方法,并探讨了闭包在循环中的常见问题及解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Demo 1:闭包初识

这里写图片描述

先要认识几点现实:

  • 函数外部无法访问函数内部的局部变量。
  • 函数内的嵌套函数可以访问函数的局部变量
  • 将嵌套函数作为闭包返回到外部空间,外部空间通过执行返回的嵌套函数可以实现外部空间对函数内部局部变量的间接访问。

关于闭包的定义及特殊性

函数在创建它的环境之外执行,那么它就是闭包。

如上例子中,函数displayName 如果在创建它的环境中:makeFunc函数内执行,则不叫闭包了。

闭包会记住创建它的环境。创建它的环境包含所在环境的局部变量,这也就是说为什么闭包能够使得外部空间访问到函数的局部变量的原因,同时也是发生内存泄漏的导火索。

Demo 2 : 返回闭包——函数工厂

这里写图片描述
上面的例子我们认识到:
* function可以不用写方法名。
* 两次对makeAdder的调用,虽然是同一makeAdder函数,但是对于返回的闭包来说,创建闭包的环境是二者是独立的,没有瓜葛。

Demo 3:闭包使用场景之:模拟私有方法

var counter=(function() {
    var privateCounter=0;
    function changeBy(val) {
        privateCounter += val;
    }

    return {
        increment:function() {
            changeBy(1);
        },

        decrement:function() {
            changeBy(-1);
        },

        value:function() {
            return privateCounter;
        }
    }
})();

咋一看,看不懂,那么像剥洋葱一样一层层的解析:

第一层: (function() {….})()

我可以如此改写一下:

var makeCounter = function() {
    var privateCounter=0;
    function changeBy(val) {
        privateCounter += val;
    }

    return {
        increment:function() {
            changeBy(1);
        },

        decrement:function() {
            changeBy(-1);
        },

        value:function() {
            return privateCounter;
        }
    }
}

var counter = makeCounter();

为什么难看懂呢?就是因为将上面两步合成了一步。使用句式是:

function() {....})()

定义闭包和执行闭包一块做了,确实奇特!

其他类似的例子

(function(global) {
    var env = global;
    (function(destroyInstance) {
        destroyInstance( % s)
    })(env.destroyInstance)
})(this)

第二层 深入闭包内部

关注一下闭包的返回:

return {
        increment:function() {
            changeBy(1);
        },

        decrement:function() {
            changeBy(-1);
        },

        value:function() {
            return privateCounter;
        }
    }

这返回的其实是一个对象。而在js中对象的定义是什么样的呢?

js对象的定义

var lennon={name:"John",year:1940}

只不过上面的demo中,每个value对应的值都是一个闭包而已。

这样写的好处是什么呢?

counter拿到了对象,那么外部空间只能调用到对象的increment,decrement,value属性,但是却无法直接调用到changeBy,privateCounter,他们被隐藏起来了,类似于java类中的private.

使用闭包时的常见问题

循环中创建闭包

这里写图片描述

问题的关键在于:

  • 闭包保留并可访问创建它的环境数据,在这里就是函数setupHelp内的数据。
  • 循环结束后,item指向了列表的最后一个。
  • 红框中的闭包在实际执行的时候,使用了函数setupHelp当前的item,也就是列表中的最后一个。
  • 当三个输入框点击的时候,显示的内容都是最后一个item.hel的内容。

如何解决呢?

  • 增加上下文环境来保留与之相对应的item数据,在这里增加了makeHelpCallback函数来封装了一层。

性能问题

这里写图片描述
除非必须,勿用闭包,对性能影响大。

参考资料

http://edu.youkuaiyun.com/course/detail/800/10909?auto_start=1
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值