JavaScript入門-函數function(二)

JavaScript入門-函數function(二)

遞歸函數

  • 什麼是遞歸函數?
    遞歸簡單理解就是,在函數體裏,調用本身。
//咱們在求一個10的階乘的時候,可能會這麼作
    //寫一個循環
    var total = 1
    for(var i=10; i>=1; i++){
        total *= i ;
    }
    這樣的for循環簡單直接。。。你們都會寫
    可是,咱們能夠寫一個函數,遞歸調用
    //遞歸函數
    function jiecheng( n ){
        if ( 1===n) return 1
        return n*jiecheng(n-1)
    }
    //調用遞歸函數
    var total = jiecheng(10)

ps:兩種不一樣的方法,雖然結果都相同,可是仍是有區別的。遞歸併無經過for循環遍歷每個數,並且代碼量變少了,看起來有點高大上。javascript

  • 其實,在遞歸調用的時候,就是按照return的特定來執行的。由於return只有在遇到一個具體的值纔會返回給調用者。
  • 而後,在調用的時候,會有一個'棧'的數據結構(先進後出,後進先出),存儲每個調用的時狀態,直到遇到一個可以有具體值的狀態,就逐層往上返回給調用者,最終的值就是你想要的值。

遞歸的缺點html

  • 每次調用本身的時候,其實一直都是在佔用着內存,佔用資源較大。

閉包

  • 什麼是閉包?
    咱們先來回顧一下,在es5裏,用var定義的變量,不論是在代碼塊裏定義,仍是在for循環裏的局部變量,咱們都可以訪問到這個變量,這就叫作全局變量。若是咱們在一個函數裏用var定義變量,就是一個局部變量了,只有內部可使用。
//定義全局變量
    var a =1;

    //函數體定義變量
    function fun(){
        var b =1;
    }

    //代碼塊裏定義變量
    {
        var c = 1
        {
            var d = 'rainbow'
        }
        
    }
    //for函數裏的變量
    for( var i = 0 ; i<10 ;i++){
        console.log(i)
    }
        console.log( a , c , d , i )//1 1 "rainbow" 10
        console.log(b)//error

ps:上面代碼能夠看出來,在JavaScript裏,除了方法體內的變量未局部變量,其餘的都是全局變量,那若是咱們想要訪問函數裏面的變量該怎麼辦呢??
這個時候,咱們就要用到閉包了。java

  1. 在函數內自定義一個方法,返回函數定義的局部變量。
  2. 調用的時候,咱們先調用外層的函數,獲得的是一個函數體,而後再一次調用,就可以獲取到outer的內部成員的變量了。
function outer(){
        var num = 10;

        funtion inner(){
            console.log(num)
        }
        return inner;
    }

    var fun = outer()
    fun()//10

    或者

    function outer() {

        var age = 20;

        return function () {//匿名函數
            return age;
        }
    }
    var age1 = outer();
    console.log(age1())//20

總結:閉包,就是在函數內部定義一個函數,把function裏私有的屬性,經過這個內部函數返回給了外面。
特色:面試

  1. 經過閉包能夠讀取函數內部的變量
  2. 每一次調用最外層的方法,實際都是從新開闢一塊內存空間., 由於返回的inner方法沒有關閉,一直佔用着內存,咱們能夠手動關閉 outer = null
  3. 在outer裏定義的變量,經過閉包獲取到的成員變量,其實都是靜態static變量,正如第2點所說,變量仍是存在內存中,並無主動釋放。

閉包的缺點瀏覽器

  • 和遞歸相似,一直佔用着內存資源,可能致使內存泄漏。

可能我本身講的不夠全,你們看看大佬的文章數據結構

完全理解閉包
http://www.javashuo.com/article/p-oqlutxhq-o.html
阮一峯老師的
http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html閉包

回調函數

回調函數有個比較逼格的名字——句柄。咱們只要知道有這麼個官方的叫法就行,之後面試或者交流的時候,也不至於聽不懂這是啥東西。
簡單理解就是,把一個函數看成參數。那麼這個函數就是回調函數。
那爲啥叫回調呢?
那是由於你執行一個方法時候,還不可以預期或者肯定會有什麼樣的結果,必須得再回過頭來調用這個函數(也就是傳的參數),獲得具體的結果。異步

function fun(callback){
        console.log(callback)
    }
    //把一個方法看成參數

    function say (value) {
    alert(value);
    }
    alert(say);
    alert(say('hi js.'));

ps:回調函數應用場景多用在使用 js 寫組件時,尤爲是組件的事件不少都須要回調函數的支持。函數

內置函數

其實,咱們js的類庫提供了不少的函數,好比常常用的console.log(),alert()等等。可是在還未學習面向對象以前,主要來了解兩個內置函數,定時器setTimeout和setInterval學習

//使用方法
    setTimeout(callback,delay);
    setInterval(callback,delay);

    function callback(){
        console.log('rainbow');
    }

    var delay = 1*1000;

    //解釋一下
    callback:定時器要執行的方法
    delay:定時器執行方法的間隔。單位ms毫秒

setTimeout、setInterval區別

  • setTimeout 只能執行一次,而setInterval一直執行。

那麼如何中止定時器呢?
每一個定時器都會返回一個定時器id,這個id在線程池中存着,咱們接收他的id,而後清除

//接收id
    var id1 = setTimeout(callback,delay);
    var id2 = setInterval(callback,delay);

    //關閉定時器
    clearTimeout(id1)
    clearInterval(id2)

ps:

  1. 關閉定時器,clearTimeout或者clearInterval均可以關閉對方的id,由於他們共用一個定時器ID poor。
  2. delay這個參數,並不會很精確,由於這和時間片輪轉有關。要想了解更多,能夠去學習一下操做系統,進程和線程是什麼。

其實,學習定時器的時候,咱們就應該瞭解一下,js裏只有單線程,並且理論是沒有異步操做的,你們口中說的那是模擬異步,那麼你們就須要瞭解一個叫作任務隊列的東西。
說到這裏,咱們就來講三個任務,其實還有不少的:

  • 渲染隊列:好比瀏覽器的渲染,ie的hasLayout
  • 事件隊列:好比點擊事件onclick
  • 定時器隊列:必定會等主程序執行完畢後再執行
    這些都是有必定執行順序的,渲染隊列->事件隊列->定時器隊列,因此定時器這個玩意,就像個棄兒,凡事都要最後才能擁有,這也就知道爲啥你給他設置delay時間的時候,不會那麼精確了。

謝謝你們能讀完這篇隨筆,鄙人學識淺薄,不少地方講的自認爲不是很深刻,也比較的俗,見諒見諒...

相關文章
相關標籤/搜索