时间:2021-05-26
前言
准确来说,闭包是基于正常的垃圾回收处理机制下的。也就是说,一般情况一个函数(函数作用域)执行完毕,里面声明的变量会全部释放,被垃圾回收器回收。但闭包利用一个技巧,让作用域里面的变量,在函数执行完之后依旧保存没有被垃圾回收处理掉。
闭包
定义
MDN定义
javascriptkit
词法作用域
闭包的三大特点为:
1、函数嵌套函数
2、内部函数可以访问外部函数的变量
3、参数和变量不会被回收。
作用域链
函数在执行的过程中,先从自己内部找变量如果找不到,再从创建当前函数所在的作用域(词法作用域)去找, 以 此往上注意找的是变量的当前的状态
作用域链的博客
函数连同它作用域链上的要找的这个变量,共同构成闭包
一般情况下使用闭包主要是为了
一个典型的闭包案例
当函数内部没有执行以下的代码时
function fn(){ speed++ console.log(speed) }return fn在代码执行完成后,函数内部的局部变量speed就会被销毁,由于全局标量speedUp一直存在(除非关闭当前页面,否则全局变量一直存在),那么函数内部的作用域就没有办法被销毁,里面有东西一直被使用,这点与浏览器的垃圾回收机制相仿,当我们执行speedUp(),他会在函数的词法作用域下去寻找,函数里面又返回了一个fn,因而形成闭包,简单的理解为
var speed = 0function fn(){ speed++ console.log(speed)}这一段代码形成一个闭包,如果不return fn,那函数内部的局部变量就会被销毁。
我们可以看看上述代码利用立即执行语句和立即执行函数可以怎么演变:
function car(){ var speed = 0 function fn(){ speed++ console.log(speed) } return fn}var speedUp = car()//1function car(){ var speed = 0 return function (){ speed++ console.log(speed) }}var speedUp = car()//2function car(speed){ return function (){ speed++ console.log(speed) }}var speedUp = car(3)//3function car(){ var speed = arguments[0] return function (){ speed++ console.log(speed) }}var speedUp = car()//4function car(){ var speed = 0 return function (){ speed++ console.log(speed) }}//5 car可以不写,则为匿名函数 var speedUp = (function car(speed){ return function (){ speed++ console.log(speed) }})(3)闭包的相关案例
如下代码输出多少?如果想输出3,那如何改造代码?
var fnArr = [];for (var i = 0; i < 10; i ++) { fnArr[i] = function(){ return i };}console.log( fnArr[3]() ) // 10同等演变
假设只有两层循环:
var fnArr = []for (var i = 0; i < 2; i ++) { fnArr[i] = (function(j){ return function(){ return j } })(i)}fnArr[3]()//1var fnArr = [] fnArr[0] = (function(j){ return function(){ return j } })(0)}fnArr[1] = (function(j){ return function(){ return j } })(1)}fnArr[3]()//2var a = (function(j){ return function(){ return j } })(0)}var b = (function(j){ return function(){ return j } })(1)}b()//3var a = (function(j){ return function(){ return j } })(0)}function fn2(j){ return function(){ return j }}var b = fn2(1)//4var a = (function(j){ return function(){ return j } })(0)}function fn2(j){ return function(){ return j } return f}var b = fn2(1)//5var a = (function(j){ return function(){ return j } })(0)}function fn2(j){ var j = arguments[0] function f(){ return j } return f}var b = fn2(1)改造后(立即执行语句,演变过程)
var fnArr = []for (var i = 0; i < 10; i ++) { fnArr[i] = (function(j){ return function(){ return j } })(i)}console.log( fnArr[3]() ) // 3var fnArr = []for (var i = 0; i < 10; i ++) { (function(i){ fnArr[i] = function(){ return i } })(i)}console.log( fnArr[3]() ) // 3var fnArr = []for (let i = 0; i < 10; i ++) { fnArr[i] = function(){ return i } }console.log( fnArr[3]() ) // 3封装一个 Car 对象
var Car = (function(){ var speed = 0; function set(s){ speed = s } function get(){ return speed } function speedUp(){ speed++ } function speedDown(){ speed-- } return { setSpeed: setSpeed, get: get, speedUp: speedUp, speedDown: speedDown }})()Car.set(30)Car.get() //30Car.speedUp()Car.get() //31Car.speedDown()Car.get() //3如下代码输出多少?如何连续输出 0,1,2,3,4
for(var i=0; i<5; i++){ setTimeout(function(){ console.log('delayer:' + i ) }, 0)}输出结果为:delayer:5(连续输出5个),执行setTimeout时,代码会挂到任务队列中区,待i遍历完成之后执行,而此时i = 5,所以输出delayer:5(连续输出5个)
修改后
for(var i=0; i<5; i++){ (function(j){ setTimeout(function(){ console.log('delayer:' + j ) }, 0)//1000-1000*j })(i)}或者
for(var i=0; i<5; i++){ setTimeout((function(j){ return function(){ console.log('delayer:' + j ) } }(i)), 0) }如下代码输出多少?
function makeCounter() { var count = 0 return function() { return count++ };}var counter = makeCounter()var counter2 = makeCounter();console.log( counter() ) // 0console.log( counter() ) // 1console.log( counter2() ) // 0console.log( counter2() ) // 1补全代码,实现数组按姓名、年纪、任意字段排序
var users = [ { name: "John", age: 20, company: "Baidu" }, { name: "Pete", age: 18, company: "Alibaba" }, { name: "Ann", age: 19, company: "Tecent" }]users.sort(byName) users.sort(byAge)users.sort(byField('company'))解答
function byName(user1, user2){ return user1.name > user2.name}function byAge (user1, user2){ return user1.age > user2.age}function byFeild(field){ return function(user1, user2){ return user1[field] > user2[field] }}users.sort(byField('company'))写一个 sum 函数,实现如下调用方式
console.log( sum(1)(2) ) // 3console.log( sum(5)(-1) ) // 4总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
JS闭包详解及实例:最近学习JS的基础知识,学习了闭包的知识点,有很多疑惑,这一段时间还是一直有在看闭包的相关知识理解就更深入了一点,下面说说我的理解。func
JavaScript闭包,是JS开发工程师必须深入了解的知识。3月份自己曾撰写博客《JavaScript闭包》,博客中只是简单阐述了闭包的工作过程和列举了几个示
在前端开发必须知道的JS之原型和继承一文中说过下面写篇闭包,加之最近越来越发现需要加强我的闭包应用能力,所以此文不能再拖了。本文讲的是函数闭包,不涉及对象闭包(
本文实例讲述了JavaScript闭包的功能与用法。分享给大家供大家参考,具体如下:理解闭包关键是理解JS的对象的本质以及垃圾收集机制。函数也是对象,也有属性,
本文实例讲述了js闭包。分享给大家供大家参考,具体如下:1.什么是闭包定义:是指有权访问另一个函数作用域中的变量的函数创建闭包:在一个函数内部创建另一个函数基本