JavaScript闭包实例代码分析


这篇文章主要介绍了JavaScript闭包实例代码分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇JavaScript闭包实例代码分析文章都会有所收获,下面我们一起来看看吧。 闭包的概念是有很多版本,不同的地方对闭包的说法不一维基百科:在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是在支持头等函数的编程语言中实现词法绑定的一种技术。MDN: 闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment词法环境)的引用的组合。个人理解:闭包是一个函数(返回一个函数)返回的函数保存了对外变量引用

functionfn(){letnum=1;returnfunction(n){returnn+num
}
}letrFn=fn()letnewN=rFn(3)//4

num 变量作用域在 fn 函数中, rFn 函数却能访问 num 变量,这就是闭包函数能访问外部函数变量。浏览器VS Code 配合 Node.js看到 Closure 中 fn 是闭包函数,其中保存 num 变量。

for(vari=1;i{console.log(i);
},i*1000);
}

输出的结果都是 6,为什么?for 循环是同步任务setTimeout 异步任务for 循环一次,就会将 setTimeout 异步任务加入到浏览器的异步任务队列中,同步任务完成之后,再从异步任务中拿新任务在线程中执行。由于 setTimeout 能够访问外部变量 i, 当同步任务完成之后,i 已经变成了6, setTimeout 中能够访问变量 i 都是 6。

for(vari=1;i{console.log(i);
},i*1000);
}

for(vari=1;i{console.log(i);
},i*1000)
})(i)
}

第三个参数意思:附加参数,一旦定时器到期,它们会作为参数传递给要执行的函数

for(vari=1;i{console.log(j);
},1000*i,i);
}

functionadd(num){returnfunction(y){returnnum+y;
};
};letincOneFn=add(1);letn=incOneFn(1);//2letdecOneFn=add(-1);letm=decOneFn(1);//0

add 函数的参数保存了闭包函数变量。在函数式编程闭包有非常重要的作用,lodash 等早期工具函数弥补 javascript 缺陷的工具函数,有大量的闭包的使用场景。创建私有变量延长变量生命周期防止滚动行为,过度执行函数,必须要节流, 节流函数接受 函数 + 时间作为参数,都是闭包中变量,以下是一个简单 setTimeout 版本:

functionthrottle(fn,time=300){vart=null;returnfunction(){if(t)return;
t=setTimeout(()=>{
fn.call(this);
t=null;
},time);
}
}

一个简单的基于 setTimeout 防抖的函数的实现

fu免费云主机域名nctiondebounce(fn,wait){vartimer=null;returnfunction(){if(timer!==null){clearTimeout(timer);
}
timer=setTimeout(fn,wait);
}
}

问题说明:父/子 组件关系, 父子组件都能使用 click 事件同时修改 state 数据, 并且子组件拿到传递下的 props 事件属性,是经过 useCallback 优化过的。也就是这个被优化过的函数,存在闭包陷阱,(保存一直是初始 state 值)

import{useState,useCallback,memo}from"react";constChildWithMemo=memo((props:any)=>{return(
); });constParent=()=>{const[count,setCount]=useState(1);consthandleClickWithUseCallback=useCallback(()=>{console.log(count); },[]);//注意这里是不能监听count,因为每次变化都会重新绑定,造成造成子组件重新渲染 return(
parentcount:{count}
); };exportdefaultParent

ChildWithMemo 使用 memo 进行优化,handleClickWithUseCallback 使用 useCallback 优化问题是点击子组件时候,输出的 count 是初始值(被闭包了)。解决办法就是使用 useRef 保存操作变量函数:

import{useState,useCallback,memo,useRef}from"react";constChildWithMemo=memo((props:any)=>{console.log("renderedchildren")return(
); });constParent=()=>{const[count,setCount]=useState(1);constcountRef=useRef(null) countRef.current=()=>{console.log(count); }return(
parentcount:{count}
); };exportdefaultParent

针对这个问题,React 曾经认可过社区提出的增加 useEvent 方案,但是后面 useEvent 语义问题被废弃了,对于渲染优化 React 采用了编译优化的方案。其实类似的问题也会发生在 useEffect 中,使用时要注意闭包陷阱。闭包不要随意定义,定义了一定找到合适的位置进行销毁。因为闭包的变量保存在内存中,不会被销毁,占用较高的内存。打开开发者工具,选择 Timeline 面板在顶部的Capture字段里面勾选 Memory点击左上角的录制按钮。在页面上进行各种操作,模拟用户的使用情况。一段时间后,点击对话框的 stop 按钮,面板上就会显示这段时间的内存占用情况。关于“JavaScript闭包实例代码分析”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“JavaScript闭包实例代码分析”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注百云主机行业资讯频道。

相关推荐: vue报错webpackJsonp is not defined怎么解决

本篇内容主要讲解“vue报错webpackJsonp is not defined怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“vue报错webpackJsonp is not defined怎么解决”吧!…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

Like (0)
Donate 微信扫一扫 微信扫一扫
Previous 03/09 09:22
Next 03/09 09:22

相关推荐