成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

站長資訊網(wǎng)
最全最豐富的資訊網(wǎng)站

簡單了解JavaScript閉包

本篇文章給大家?guī)砹岁P(guān)于JavaScript的相關(guān)知識(shí),其中主要介紹了關(guān)于JavaScript閉包的相關(guān)問題,閉包的概念有很多版本,不同的地方對(duì)閉包的說法不一,下面一起來看一下,希望對(duì)大家有幫助。

簡單了解JavaScript閉包

什么是閉包?

閉包的概念是有很多版本,不同的地方對(duì)閉包的說法不一

維基百科:在計(jì)算機(jī)科學(xué)中,閉包(英語:Closure),又稱詞法閉包(Lexical Closure)或函數(shù)閉包(function closures),是在支持頭等函數(shù)的編程語言中實(shí)現(xiàn)詞法綁定的一種技術(shù)。

MDN: 閉包(closure)是一個(gè)函數(shù)以及其捆綁的周邊環(huán)境狀態(tài)(lexical environment詞法環(huán)境)的引用的組合。

個(gè)人理解:

  • 閉包是一個(gè)函數(shù)(返回一個(gè)函數(shù))
  • 返回的函數(shù)保存了對(duì)外變量引用

一個(gè)簡單的示例

function fn() {    let num = 1;    return function (n) {        return n + num     } }let rFn = fn()let newN = rFn(3) // 4
登錄后復(fù)制

num 變量作用域在 fn 函數(shù)中, rFn 函數(shù)卻能訪問 num 變量,這就是閉包函數(shù)能訪問外部函數(shù)變量。

從瀏覽器調(diào)試和 VSCode Nodejs 調(diào)試看閉包

  • 瀏覽器

簡單了解JavaScript閉包

  • VS Code 配合 Node.js

簡單了解JavaScript閉包

看到 Closure 中 fn 是閉包函數(shù),其中保存 num 變量。

一個(gè)經(jīng)典的閉包:單線程事件機(jī)制+循環(huán)問題,以及解決辦法

for (var i = 1; i <= 5; i++) {  setTimeout(() => {    console.log(i);   }, i * 1000); }
登錄后復(fù)制

登錄后復(fù)制

輸出的結(jié)果都是 6,為什么?

  • for 循環(huán)是同步任務(wù)
  • setTimeout 異步任務(wù)

for 循環(huán)一次,就會(huì)將 setTimeout 異步任務(wù)加入到瀏覽器的異步任務(wù)隊(duì)列中,同步任務(wù)完成之后,再從異步任務(wù)中拿新任務(wù)在線程中執(zhí)行。由于 setTimeout 能夠訪問外部變量 i, 當(dāng)同步任務(wù)完成之后,i 已經(jīng)變成了6, setTimeout 中能夠訪問變量 i 都是 6。

解決辦法1:使用 let 聲明

for (var i = 1; i <= 5; i++) {  setTimeout(() => {    console.log(i);   }, i * 1000); }
登錄后復(fù)制

登錄后復(fù)制

解決辦法2:自執(zhí)行函數(shù) + 閉包

for (var i = 1; i <= 5; i++) {   (function(i){      setTimeout(() => {    console.log(i);   }, i * 1000)   })(i) }
登錄后復(fù)制

解決辦法3:setTimeout 傳遞第三參數(shù)

第三個(gè)參數(shù)意思:附加參數(shù),一旦定時(shí)器到期,它們會(huì)作為參數(shù)傳遞給要執(zhí)行的函數(shù)

for (var i = 1; i <= 5; i++) {  setTimeout((j) => {    console.log(j);   }, 1000 * i, i); }
登錄后復(fù)制

閉包與函數(shù)科里化

function add(num) {  return function (y) {    return num + y;   }; };let incOneFn = add(1); let n = incOneFn(1);  // 2let decOneFn = add(-1); let m = decOneFn(1); // 0
登錄后復(fù)制

add 函數(shù)的參數(shù)保存了閉包函數(shù)變量。

實(shí)際作用

在函數(shù)式編程閉包有非常重要的作用,lodash 等早期工具函數(shù)彌補(bǔ) javascript 缺陷的工具函數(shù),有大量的閉包的使用場景。

使用場景

  • 創(chuàng)建私有變量
  • 延長變量生命周期

節(jié)流函數(shù)

防止?jié)L動(dòng)行為,過度執(zhí)行函數(shù),必須要節(jié)流, 節(jié)流函數(shù)接受 函數(shù) + 時(shí)間作為參數(shù),都是閉包中變量,以下是一個(gè)簡單 setTimeout 版本:

function throttle(fn, time=300){    var t = null;    return function(){        if(t) return;         t = setTimeout(() => {             fn.call(this);             t = null;         }, time);     } }
登錄后復(fù)制

防抖函數(shù)

一個(gè)簡單的基于 setTimeout 防抖的函數(shù)的實(shí)現(xiàn)

function debounce(fn,wait){    var timer = null;    return function(){        if(timer !== null){            clearTimeout(timer);         }         timer = setTimeout(fn,wait);     } }
登錄后復(fù)制

React.useCallback 閉包陷阱問題

問題說明:父/子 組件關(guān)系, 父子組件都能使用 click 事件同時(shí)修改 state 數(shù)據(jù), 并且子組件拿到傳遞下的 props 事件屬性,是經(jīng)過 useCallback 優(yōu)化過的。也就是這個(gè)被優(yōu)化過的函數(shù),存在閉包陷阱,(保存一直是初始 state 值)

import { useState, useCallback, memo } from "react";const ChildWithMemo = memo((props: any) => {  return (    <div>       <button onClick={props.handleClick}>Child click</button>     </div>   ); });const Parent = () => {  const [count, setCount] = useState(1);  const handleClickWithUseCallback = useCallback(() => {    console.log(count);   }, []); // 注意這里是不能監(jiān)聽 count, 因?yàn)槊看巫兓紩?huì)重新綁定,造成造成子組件重新渲染    return (    <div>       <div>parent count : {count}</div>       <button onClick={() => setCount(count + 1)}>click</button>       <ChildWithMemo handleClick={handleClickWithUseCallback} />     </div>   ); };export default Parent
登錄后復(fù)制

  • ChildWithMemo 使用 memo 進(jìn)行優(yōu)化,
  • handleClickWithUseCallback 使用 useCallback 優(yōu)化

問題是點(diǎn)擊子組件時(shí)候,輸出的 count 是初始值(被閉包了)。

解決辦法就是使用 useRef 保存操作變量函數(shù):

import { useState, useCallback, memo, useRef } from "react";const ChildWithMemo = memo((props: any) => {  console.log("rendered children")  return (    <div>       <button onClick={() => props.countRef.current()}>Child click</button>     </div>   ); });const Parent = () => {  const [count, setCount] = useState(1);  const countRef = useRef<any>(null)    countRef.current = () => {    console.log(count);   }  return (    <div>       <div>parent count : {count}</div>       <button onClick={() => setCount(count + 1)}>click</button>       <ChildWithMemo countRef={countRef} />     </div>   ); };export default Parent
登錄后復(fù)制

針對(duì)這個(gè)問題,React 曾經(jīng)認(rèn)可過社區(qū)提出的增加 useEvent 方案,但是后面 useEvent 語義問題被廢棄了,對(duì)于渲染優(yōu)化 React 采用了編譯優(yōu)化的方案。其實(shí)類似的問題也會(huì)發(fā)生在 useEffect 中,使用時(shí)要注意閉包陷阱。

性能問題

  • 閉包不要隨意定義,定義了一定找到合適的位置進(jìn)行銷毀。因?yàn)殚]包的變量保存在內(nèi)存中,不會(huì)被銷毀,占用較高的內(nèi)存。

使用 chrome 面板功能 timeline + profiles 面板

  1. 打開開發(fā)者工具,選擇 Timeline 面板
  2. 在頂部的Capture字段里面勾選 Memory
  3. 點(diǎn)擊左上角的錄制按鈕。
  4. 在頁面上進(jìn)行各種操作,模擬用戶的使用情況。
  5. 一段時(shí)間后,點(diǎn)擊對(duì)話框的 stop 按鈕,面板上就會(huì)顯示這段時(shí)間的內(nèi)存占用情況。

贊(0)
分享到: 更多 (0)
?
網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)
JAZZJAZZ国产精品| 一边做饭一边躁狂我会怎么样呢| 天天综合天天爱天天做| 无码免费伦费影视在线观看| 亚洲AV成人片无码网站| 亚洲伊人久久综合成人网站| 中文精品久久久久鬼色| C交人Z000Z000XXⅩ| 成人爽A毛片免费| 国产精品久久久久久精品三级| 国内盗摄视频一区二区三区| 久久久久99精品成人片牛牛影视| 麻花豆传媒剧国产MV在线观看| 欧美极品少妇XXXXⅩO69| 日本适合十八岁以上人群的护肤品 | 四虎精品成人免费视频| 亚洲 成人 无码 在线观看| 野花电影3在线观看免费| 99精产国品一二三产区区| 吃瓜爆料黑料网站| 国产农村一国产农村无码毛片| 久久99久久99精品免观看| 男女一边摸一边做爽爽| 日韩免费一区二区三区高清| 亚洲AV日韩AV无码AV一区二| 中国女篮世界排名| 大香煮伊在2020一二三久| 国产在线精品一区二区中文| 老熟女多次高潮露脸视频| 日本熟妇色丰满少妇wwwww色| 无码视频一区二区三区在线观看| 亚洲日韩精品无码专区加勒比| AV人摸人人人澡人人超碰小说| 国产成A人片在线观看视频| 精品少妇无码AV在线播放| 欧美极品少妇XXXXⅩ高跟鞋| 午夜亚洲AⅤ无码高潮片苍井空| 野花高清在线观看免费| 超碰97人人做人人爱可以下载| 国模无码视频一区二区三区| 哦┅┅快┅┅用力啊┅┅村妇| 天天天天做夜夜夜夜做无码| 一本一道人人妻人人妻ΑV| 成熟交BGMBGMBGM中国| 精品人妻一区二区三区浪潮在线| 欧亚精品卡一卡二卡三7174| 亚洲AV无码国产精品麻豆天美| 99精品一区二区三区无码吞精| 国产精品无码免费视频二三区| 巨胸喷奶水WWW视频网站| 射精专区一区二区朝鲜| 野花香在线观看免费观看大全动漫 | 成人亚洲AV日韩AV欧v| 久久精品国产亚洲精品| 色一情一乱一伦麻豆| 一区二区三区精品偷拍| 国产AV一区二区三区天堂综合网| 久久婷婷色五月综合图区| 他的舌头探进蜜源毛毛虫说说 | 成人无码精品无码社区| 久久久亚洲裙底偷窥综合 | 动漫成人无码免费视频在线播 | AV狠狠色超碰丁香婷婷综合久久| 国模生殖欣赏337METCN| 男男高H啊灌满了高潮视频| 国语自产拍精品香蕉在线播放| 黑人巨茎大战俄罗斯美女| 欧美另类VIDEOSBESTS| 亚洲AV成人综合五月天在线观看 | 天天玩天天玩天天玩| 91精品人妻一区二区三区蜜桃| 国产精品亚洲А∨无码播放麻豆| 久久99国产精品久久99果冻传| 久久精品国产99国产精品导航| 女朋友特别闷骚很吸引别人| 强行入侵粗暴完整版| 亚洲精品偷拍自综合网| 俄罗斯性孕妇孕交| 免费看B站直播APP下载| 亚洲国产精品一区二区久久| 夫妻之间的100种插秧法| 哦┅┅快┅┅用力啊┅┅在线观看| 亚洲国产午夜精品理论片妓女| 国产98色在线 | 国| 欧美性猛交XXXX乱大交极品| 野草乱码一二三四区别在哪| 国产精品一区理论片| 日韩成人无码一区二区三区| 综合久久国产九一剧情麻豆| 精品国产一区二区三区AV片 | 亚洲国产精品VA在线观看香蕉| 丰满人妻熟妇乱又伦精品视| 浓精喷进老师黑色丝袜| 阳茎伸入女人的阳道免费视频| 国产揄拍国产精品| 视频免费网站入口| 把腿扒开让我舔免费视频| 免费女人18毛片A毛片视频| 久久综合久久鬼色| 亚洲AV熟女高潮30P| 国产成人精欧美精品视频| 亲生乖女好紧H下| 丰满少妇被猛男猛烈进入久久| 国产乱人伦真实精品视频| 久久五月丁香合缴情网| 亚洲高清国产拍精品熟女| 国产精品久久久久久久久软件 | 免费真人视频网站直播下载| 亚洲最新版AV无码中文字幕| 好紧好深好大乳无码中文字幕| 挺进邻居丰满少妇的身体| 刺激交换经历过程小说| 人人妻人人妻人人人人妻| FREEⅩXX性欧美HD丝袜| 牛和人交VIDEOS欧美3D| 中文乱码精品一区二区三区人妻| 久久久精品成人免费观看国产| 亚洲精品亚洲人成在线观看麻豆| 国内外精品激情刺激在线| 香蕉尹人综合在线观看| 国产精品青草久久福利不卡| 天天摸天天摸色综合舒服网| 国产★蜜臀AV无码| 天堂А√在线最新版在线8| 丰满少妇被猛烈进入无码| 色综合久久综合欧美综合网| 成熟丰满熟妇偷拍XXXXX| 色婷婷亚洲一区二区三区| 吃瓜爆料黑料网站| 少妇性生生活视频在线观看| 父母全家儿女大联欢第14集| 深入浅出糙汉X软妹V1V| 国99精品无码一区二区三区| 天天狠天天透天干天天怕| 粉嫩AV一二三区免费| 少妇把腿扒开让我添69动态图| 国产AV免费一区二区三区| 天堂А√在线中文在线| 国产美女丝袜一级肛交蜜桃| 亚洲AV无码精品狠狠爱| 交换配乱吟粗大SNS840| 亚洲熟妇少妇任你躁在线观看无码| 久久精品亚洲精品国产色婷| 一区二区狠狠色丁香久久婷婷| 免费A级毛片波多野结衣| 99久久亚洲精品无码毛片 | 顶级欧美RAPPER| 无码精品人妻一区二区三区在线 | 欧美日韩一区二区三区人妻 | 国产精品无码久久综合网| 亚洲GV天堂GV无码男同在线观| 精品人妻无码中字系列 | 内谢少妇XXXXX8老少交| 爆乳上司JULIA中文字幕| 少妇精品久久久久www| 国产色视频一区二区三区QQ号 | 我是你可爱的小猫| 狠狠躁夜夜躁人爽碰88A| 伊人伊成久久人综合 成人| 欧美成人精品高清在线观看| 把女人弄爽特黄A大片| 婷婷5月女内射AV| 狠狠色噜噜狠狠狠狠7777米奇| 伊人久久大香线蕉无码| 强奷高H猛烈失禁潮喷播放| 公交车里抓着摇曳的手环诗情| 亚洲AⅤ无码天堂在线观看| 久久久久国产精品嫩草影院| AV在线中文字幕不卡电影网| 视频一区二区三区日韩| 狠狠躁夜夜躁人人爽天天天天| 伊人精品久久久久7777| 人妻少妇偷人精品视频| 国产精品久久久爽爽爽麻豆色哟哟 | 亚洲 中文字幕在线播| 久久人人爽人人爽人人片AVY| H漫全彩纯肉无码网站| 完整版免费AV片| 久久精品国产精品亚洲精品| BBBBBB嫩BBBBBB| 性VIDEOSTV另类极品| 鲁鲁夜夜天天综合视频| 粗大的内捧猛烈进出无码| 亚洲AV永久无码精品尤物在线| 免费十大软件大全下载安装| 国产94在线 | 亚洲| 亚洲色偷偷综合亚洲av伊人| 青草青草久热精品视频国产4| 国产免费AV片在线观看| 中国人も日本人も汉字を| 色欲av夜夜嗨av性色av| 精品无码一区二区三区水蜜桃| JAPAN色系VIDEOS护士| 小奶瓶(产奶)沈姜| 美女裸体无遮挡免费视频网站| 五月丁香伊人久久91视频| 黑人巨大粗物挺进了少妇| 一区蜜桃中文不卡在线| 亚洲色大成网站WWW尤物| 久久精品国产99国产精品澳门|