真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

JavaScript閉包實(shí)例代碼分析

這篇文章主要介紹了JavaScript閉包實(shí)例代碼分析的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡(jiǎn)單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇JavaScript閉包實(shí)例代碼分析文章都會(huì)有所收獲,下面我們一起來(lái)看看吧。

成都創(chuàng)新互聯(lián)公司服務(wù)項(xiàng)目包括陳巴爾虎網(wǎng)站建設(shè)、陳巴爾虎網(wǎng)站制作、陳巴爾虎網(wǎng)頁(yè)制作以及陳巴爾虎網(wǎng)絡(luò)營(yíng)銷(xiāo)策劃等。多年來(lái),我們專(zhuān)注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,陳巴爾虎網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到陳巴爾虎省份的部分城市,未來(lái)相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

什么是閉包?

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

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

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

個(gè)人理解:

  • 閉包是一個(gè)函數(shù)(返回一個(gè)函數(shù))

  • 返回的函數(shù)保存了對(duì)外變量引用

一個(gè)簡(jiǎn)單的示例

function fn() {    let num = 1;    return function (n) {        return n + num
    }
}let rFn = fn()let newN = rFn(3) // 4

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

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

  • 瀏覽器

JavaScript閉包實(shí)例代碼分析

  • VS Code 配合 Node.js

JavaScript閉包實(shí)例代碼分析

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

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

for (var i = 1; i <= 5; i++) {  setTimeout(() => {    console.log(i);
  }, i * 1000);
}

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

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

  • setTimeout 異步任務(wù)

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

解決辦法1:使用 let 聲明

for (var i = 1; i <= 5; i++) {  setTimeout(() => {    console.log(i);
  }, i * 1000);
}

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

for (var i = 1; i <= 5; i++) {
  (function(i){      setTimeout(() => {    console.log(i);
  }, i * 1000)
  })(i)
}

解決辦法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);
}

閉包與函數(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

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

實(shí)際作用

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

使用場(chǎng)景

  • 創(chuàng)建私有變量

  • 延長(zhǎng)變量生命周期

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

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

function throttle(fn, time=300){    var t = null;    return function(){        if(t) return;
        t = setTimeout(() => {
            fn.call(this);
            t = null;
        }, time);
    }
}

防抖函數(shù)

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

function debounce(fn,wait){    var timer = null;    return function(){        if(timer !== null){            clearTimeout(timer);
        }
        timer = setTimeout(fn,wait);
    }
}

React.useCallback 閉包陷阱問(wèn)題

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

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

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

  • handleClickWithUseCallback 使用 useCallback 優(yōu)化

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

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

import { useState, useCallback, memo, useRef } from "react";const ChildWithMemo = memo((props: any) => {  console.log("rendered children")  return (    
       props.countRef.current()}>Child click     
  ); });const Parent = () => {  const [count, setCount] = useState(1);  const countRef = useRef(null)   countRef.current = () => {    console.log(count);   }  return (    
      
parent count : {count}
       setCount(count + 1)}>click            
  ); };export default Parent

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

性能問(wèn)題

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

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

  1. 打開(kāi)開(kāi)發(fā)者工具,選擇 Timeline 面板

  2. 在頂部的Capture字段里面勾選 Memory

  3. 點(diǎn)擊左上角的錄制按鈕。

  4. 在頁(yè)面上進(jìn)行各種操作,模擬用戶的使用情況。

  5. 一段時(shí)間后,點(diǎn)擊對(duì)話框的 stop 按鈕,面板上就會(huì)顯示這段時(shí)間的內(nèi)存占用情況。

關(guān)于“JavaScript閉包實(shí)例代碼分析”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對(duì)“JavaScript閉包實(shí)例代碼分析”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


當(dāng)前標(biāo)題:JavaScript閉包實(shí)例代碼分析
本文地址:http://weahome.cn/article/ijhcjs.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部