<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>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                閉包詳解 閉包的應該都聽過,但到底什么是閉包呢? 閉包是由函數及其相關引用環境組合而成的實體(即:閉包=函數+引用環境)。 “官方”的解釋是:所謂“閉包”,指的是一個擁有許多變量和綁定了這些變量的環境的表達式(通常是一個函數),因而這些變量也是該表達式的一部分。 維基百科講,閉包(Closure),是引用了自由變量的函數。這個被引用的自由變量將和這個函數一同存在,即使已經離開了創造它的環境也不例外。所以,有另一種說法認為閉包是由函數和與其相關的引用環境組合而成的實體。閉包在運行時可以有多個實例,不同的引用環境和相同的函數組合可以產生不同的實例。 看著上面的描述,會發現閉包和匿名函數似乎有些像。可是可能還是有些云里霧里的。因為跳過閉包的創建過程直接理解閉包的定義是非常困難的。目前在JavaScript、Go、PHP、Scala、Scheme、Common Lisp、Smalltalk、Groovy、Ruby、 Python、Lua、objective c、Swift 以及Java8以上等語言中都能找到對閉包不同程度的支持。通過支持閉包的語法可以發現一個特點,他們都有垃圾回收(GC)機制。 javascript應該是普及度比較高的編程語言了,通過這個來舉例應該好理解寫。看下面的代碼,只要關注script里方法的定義和調用就可以了。 ~~~ <!DOCTYPE html> <html lang="zh"> <head> <title></title> </head> <body> </body> </html> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript"></script> <script> function a(){ var i=0; function b(){ console.log(++i); document.write("<h1>"+i+"</h1>"); } return b; } $(function(){ var c=a(); c(); c(); c(); //a(); //不會有信息輸出 document.write("<h1>=============</h1>"); var c2=a(); c2(); c2(); }); </script> ~~~ 這段代碼有兩個特點: 函數b嵌套在函數a內部 函數a返回函數b 這樣在執行完var c=a()后,變量c實際上是指向了函數b(),再執行函數c()后就會顯示i的值,第一次為1,第二次為2,第三次為3,以此類推。 其實,這段代碼就創建了一個閉包。因為函數a()外的變量c引用了函數a()內的函數b(),就是說: 當函數a()的內部函數b()被函數a()外的一個變量引用的時候,就創建了一個閉包。 在上面的例子中,由于閉包的存在使得函數a()返回后,a中的i始終存在,這樣每次執行c(),i都是自加1后的值。 從上面可以看出閉包的作用就是在a()執行完并返回后,閉包使得Javascript的垃圾回收機制GC不會收回a()所占用的資源,因為a()的內部函數b()的執行需要依賴a()中的變量i。 在給定函數被多次調用的過程中,這些私有變量能夠保持其持久性。變量的作用域僅限于包含它們的函數,因此無法從其它程序代碼部分進行訪問。不過,變量的生存期是可以很長,在一次函數調用期間所創建所生成的值在下次函數調用時仍然存在。正因為這一特點,閉包可以用來完成信息隱藏,并進而應用于需要狀態表達的某些編程范型中。 下面來想象另一種情況,如果a()返回的不是函數b(),情況就完全不同了。因為a()執行完后,b()沒有被返回給a()的外界,只是被a()所引用,而此時a()也只會被b()引 用,因此函數a()和b()互相引用但又不被外界打擾(被外界引用),函數a和b就會被GC回收。所以直接調用a();是頁面并沒有信息輸出。 下面來說閉包的另一要素引用環境。c()跟c2()引用的是不同的環境,在調用i++時修改的不是同一個i,因此兩次的輸出都是1。函數a()每進入一次,就形成了一個新的環境,對應的閉包中,函數都是同一個函數,環境卻是引用不同的環境。這和c()和c()的調用順序都是無關的。 Go的閉包 Go語言是支持閉包的,這里只是簡單地講一下在Go語言中閉包是如何實現的。 下面我來將之前的JavaScript的閉包例子用Go來實現。 ~~~ package main import ( "fmt" ) func a() func() int { i := 0 b := func() int { i++ fmt.Println(i) return i } return b } func main() { c := a() c() c() c() a() //不會輸出i } ~~~ 輸出結果: ~~~ 1 2 3 ~~~ 可以發現,輸出和之前的JavaScript的代碼是一致的。具體的原因和上面的也是一樣的,這說明Go語言是支持閉包的。 閉包復制的是原對象指針,這就很容易解釋延遲引用現象。 ~~~ package main import "fmt" func test() func() { x := 100 fmt.Printf("x (%p) = %d\n", &x, x) return func() { fmt.Printf("x (%p) = %d\n", &x, x) } } func main() { f := test() f() } ~~~ 輸出: ~~~ x (0xc42007c008) = 100 x (0xc42007c008) = 100 ~~~ 在匯編層 ,test 實際返回的是 FuncVal 對象,其中包含了匿名函數地址、閉包對象指針。當調 匿名函數時,只需以某個寄存器傳遞該對象即可。 ~~~ FuncVal { func_address, closure_var_pointer ... } ~~~ Go 語言遞歸函數 遞歸,就是在運行的過程中調用自己。 一個函數調用自己,就叫做遞歸函數。 構成遞歸需具備的條件: 1. 子問題須與原始問題為同樣的事,且更為簡單。 2. 不能無限制地調用本身,須有個出口,化簡為非遞歸狀況處理。 數字階乘 一個正整數的階乘(factorial)是所有小于及等于該數的正整數的積,并且0的階乘為1。自然數n的階乘寫作n!。1808年,基斯頓·卡曼引進這個表示法。 ~~~ package main import "fmt" func factorial(i int) int { if i <= 1 { return 1 } return i * factorial(i-1) } func main() { var i int = 7 fmt.Printf("Factorial of %d is %d\n", i, factorial(i)) } ~~~ 輸出結果: ~~~ Factorial of 7 is 5040 ~~~ 斐波那契數列(Fibonacci) 這個數列從第3項開始,每一項都等于前兩項之和。 ~~~ package main import "fmt" func fibonaci(i int) int { if i == 0 { return 0 } if i == 1 { return 1 } return fibonaci(i-1) + fibonaci(i-2) } func main() { var i int for i = 0; i < 10; i++ { fmt.Printf("%d\n", fibonaci(i)) } } ~~~ 輸出結果: ~~~ 0 1 1 2 3 5 8 13 21 34 ~~~
                  <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>

                              哎呀哎呀视频在线观看