<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                >[success] # 什么是閉包 ~~~ 1.用'js的秘密花園'解釋閉包:當前作用域總是能夠訪問外部作用域中的變量, 用'js高級程序語言設計'解釋閉包:有權訪問另一個函數作用域中的變量的函數 用MDN:函數和對其周圍狀態(lexical environment,詞法環境)的引用捆綁在一起構成閉包= (closure)。也就是說,閉包可以讓你從內部函數訪問外部函數作用域。在 JavaScript 中,每當函數被創建 ,就會在函數生成時生成閉包。 2.簡單的總結兩句話: 閉包 (Closure):函數和其周圍的狀態(詞法環境)的引用捆綁在一起形成閉包。 可以在另一個作用域中調用一個函數的內部函數并訪問到該函數的作用域中的成員 3.'閉包的本質':函數在執行的時候會放到一個執行棧上當函數執行完畢之后會從執行棧上移除,但是 堆上的作用域成員因為被外部引用不能釋放,因此內部函數依然可以訪問外部函數的成員 4.最常見的閉包方式'函數嵌套函數 或者對象,讓其達到值讀取外層函數的變量值,進行一種數據緩存' 4.1. 從廣義的角度來說:JavaScript中的函數都是閉包;因為js函數都可以訪問外部全局 作用域變量 4.2.從狹義的角度來說:JavaScript中一個函數,如果訪問了外層作用域的變量,那么它是一個閉包 ~~~ >[danger] ##### 先知道作用域鏈 ~~~ 1.簡單講'js'的作用域鏈就是從內到外,就近原則 ~~~ ~~~ // 首先根據作用域鏈從內向外找,func2 中的 // 打印b和a先在func2中找沒有,就在向外面一層 // 找到了因此打印 2,1 // func1 中打印的c報錯,因為c 是在func2中,func1 // 中的c要遵守從內向外,他的內是func1沒有c,在往外一層 // 全局也沒有c var a = 1 var func1 = function () { var b = 2 var func2 = function () { var c = 3 console.log(b) // 2 console.log(a) // 1 } func2() console.log(c) // 報錯 } func1() ~~~ >[danger] ##### 在知道一下變量的聲明周期 ~~~ 1.首先全局變量的生命周期是永久的,觸發人為去銷毀全局變量,但函數內 的局部變量會隨著函數調用完,就會將自己內部的變量銷毀 2.下面代碼其中'test' 就是典型的全局變量,也就是說全局會一直有一個'test'的 方法,'test()' 是函數的執行,當他結束了也就是這個的調用結束,js 就會把這個 調用的函數的'a'銷毀,但注意這里指的是調用函數的'a',不是函數'test'的'a' ~~~ ~~~ var test = function() { var a = 1 // 退出函數后局部變量被銷毀 console.log(a) } // 我執行完了我內部a做完事了被銷毀了 test() ~~~ >[danger] ##### 舉個例子解釋閉包的本質 ~~~ 1.聲明一個pay ,此時執行的函數once 返回的函數被外部成員聲明的pay被引用了,因此不能釋放, 現在{1} 因為被pay 引用不能釋放,因此函數內部調用的done 同樣也不能被釋放, 形成下面的結果 第二次調用pay 是沒有打印的,因為第一次已經改變了done的值,現在大家都沒被釋放,第二次用 的是done 改變后的值因此不會打印 ~~~ ~~~ // once function once(fn) { let done = false return function () { // {1} if (!done) { done = true return fn.apply(this, arguments) } } } let pay = once(function (money) { console.log(`支付:${money} RMB`) }) // 只會支付一次 pay(5) pay(5) ~~~ >[danger] ##### 引用js高級程序語言設計中的例子說明 ~~~ function compare(value1, value2){ if (value1 < value2){ return -1; } else if (value1 > value2){ return 1; } else { return 0; } } ~~~ ![](https://img.kancloud.cn/78/e0/78e02345d2a1755cb7e5eac066379b10_556x212.png) >[danger] ##### 知道上面這些來理解閉包 ~~~ 1.函數內部變量是無法在外部訪問的(即全局變量和局部變量的區別),因此使用閉包的作用, 就具備實現了能在外部訪問某個函數內部變量的功能,讓這些內部變量的值始終可以保存在內存中 2.但是如果利用'作用域鏈'的特性,當訪問一個變量時,代碼解釋器會首先在當前的作用域查找, 如果沒找到,就去父級作用域去查找,直到找到該變量或者不存在父級作用域中 3.再來看下面案例 做一個假設如果fun2 和fun1中都沒有a變量(防止誤導下面代碼都有但是目前是假設) ,fun2 首先看自己內部有沒有 'a' 變量 =》再到fun1找=》再到全局,注意這個過程如果fun2 沒有某個 變量他們去找fun1的 ,此時就像 用'js高級程序語言設計'解釋閉包:有權訪問另一個函數作用域中的變量的函數 4.閉包產生的本質就是:'當前環境中存在指向父級作用域的引用' ~~~ ~~~ var a = 1; function fun1() { var a = 2 function fun2() { var a = 3; console.log(a);//3 } } ~~~ >[danger] ##### 遵循 只需要讓父級作用域的引用存在即可 ~~~ 1.閉包實際只需要讓父級作用域的引用存在即可 2.下面案例fun3 一直引用fun1的作用域 他們就形成閉包 3.不是非要遵循 函數內部return返回一個函數 ~~~ ~~~ var fun3; function fun1() { var a = 2 fun3 = function() { console.log(a); } } fun1(); fun3(); ~~~ ~~~ function a() { let x = 1 a = function () { x += 1 console.log(x) } } a() // 當a執行完后內部定義a = function(){} 因為沒有let const var 等聲明此時a已經定義在全局 a() // 2 重新定義的a 內部x 引用上級作用域即之前a中let x= 1 內存因為被新的a=function 占用未被釋放 a() // 3 因此也形成閉包 ~~~ >[danger] ##### 簡單的閉包案例 ~~~ 1.剛才理論如果退出函數,應該內部局部變量會被銷毀,但現在看來'num', 沒有按照我們想的去重置,是因為'test'中的匿名函數在使用num,因此此時 的局部變量'num' 沒有被銷毀 2.可以看例子二,例子二中的'num' 是全局的,因此不會被銷毀,也出現了例子 一的效果,現在可以抽象理解,閉包函數中,被使用的外部變量,相當于該調用 函數的"全局變量",正式因為如此就出現了案例一的效果 ~~~ * 案例一 ~~~ function test() { var num = 1 return function(){ console.log(++num) } } const useTest = test() useTest() // 2 useTest() // 3 useTest() // 4 ~~~ * 案例二 ~~~ var num = 1 function test() { console.log(++num) } test() // 2 test() // 3 test() // 4 ~~~ >[danger] ##### 引用js高級程序語言設計中的例子說明 ~~~ //創建函數 var compareNames = createComparisonFunction("name"); //調用函數 var result = compareNames({ name: "Nicholas" }, { name: "Greg" }); //解除對匿名函數的引用(以便釋放內存) compareNames = null; ~~~ ![](https://img.kancloud.cn/9d/0d/9d0de7bfeef6c89e945fab2f44a255b7_509x275.png) >[danger] ##### 簡單的總結理解 ~~~ /* 1.在整個程序運行的時候,首先 js 會將這些定義的變量 函數 往上提 其中 函數的優先大于變量的,提上去的這些是全局的不會被銷毀 2.當函數調用的時候 就會是棧的形式 先進后出,這些函數的調用都會被壓進 棧中依次執行 3.正常函數定義 好了后 會有函數的調用,調用結束后調用這個函數 內部變量使用 就結束了 是調用的不是 定義的 4.閉包是啥,就是讓函數這些內部原本執行調用后就要被銷毀的變量像全局變量一樣 不被銷毀 */ 2. 下面有兩個案例分別為案例一和案例二,閉包是內部的作用域訪問外部作用域,作用域是在編 譯階段,案例一內部函數嵌套函數符合在編譯階段,案例二回調函數雖然在內部但是在執行階段 案例一典型的閉包案例,案例二在我目前的理解中不算閉包,通過控制臺斷點也可以觀察到案例 一有closer閉包的標志,案列二沒有 // 案例一 function test() { const a = { num: 1 } function innerTest() { ++a.num console.log(a.num) } innerTest() } test() // 案例二 function test(callback) { const a = 1 callback && callback(1) // 被調用了結束了 } test((num)=>{console.log(num)}) ~~~ >[info] ## 轉換閉包的思想 ~~~ 1.利用閉包的思想可以做一些相同重復有規律的封裝成方法 ~~~ >[danger] ##### 求某個數的平方或者立方 或者N次方 ~~~ // 求某個數的平方或者立方 或者N次方 // --------------普通邏輯寫法------------- // 你要求那個我就寫那個就完事了 const num1 = Math.pow(5, 2) // 5的平方 const num2 = Math.pow(10, 2) // 10的平方 const num3 = Math.pow(3, 3) // 3的三次方 // 尋找規律,如果是平方性質的其實第二個參數都是一樣的 // 也可以理解成同開方的本質其實是第二個參數是一致的 // 如果在寫的時候通過閉包的形式將 第二個參數進行保存,就可以復用 function makePower(power) { return function (x) { return Math.pow(x, power) } } const power2 = makePower(2) const power3 = makePower(3) const num4 = power2(2) // 4 const num5 = power2(3) // 9 console.log(num1) console.log(num2) console.log(num3) console.log(num4) console.log(num5) ~~~ >[danger] ##### 業績獎金 ~~~ // 第一個數是基本工資,第二個數是績效工資 function makeSalary(x) { return function (y) { return x + y } } let salaryLevel1 = makeSalary(1500) let salaryLevel2 = makeSalary(2500) console.log(salaryLevel1(2000)) console.log(salaryLevel1(3000)) ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看