国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JS函數表達式的特征和遞歸

mudiyouyou / 1384人閱讀

摘要:函數表達式是中的一個既強大又容易令人困惑的特性。函數表達式有幾種不同的語法形式。匿名函數的屬性是空字符竄。在把函數當成值使用的情況下,都可以使用匿名函數。不過,這并不是匿名函數唯一的用途。不過我們可以使用命名函數表達式來達成相同的成果。

前言:最近在細讀Javascript高級程序設計,對于我而言,中文版,書中很多地方翻譯的差強人意,所以用自己所理解的,嘗試解讀下。如有紕漏或錯誤,會非常感謝您的指出。文中絕大部分內容引用自《JavaScript高級程序設計第三版》。

函數表達式是JavaScript中的一個既強大又容易令人困惑的特性。

定義函數的方式有兩種: 一種是函數聲明,另外一種就是函數表達式。

函數聲明的語法是這樣的。

function functionName(arg0, arg1, arg2) {
    //函數體
}

語法:首先是function關鍵字,然后是函數的名字,這就是指定函數名的方式。

Firefox、Safari、Chrome和Opera都給函數定義了一個非標準的name屬性,通過這個屬性可以訪問到給函數指定的名字。
這個屬性的值永遠等于跟在function關鍵字后面的標識符。

//只在Firefox、Safari、Chrome和Opera有效

function functionName(arg0, arg1, arg2) {

}

console.log(functionName.name); // "functionName"

關于函數聲明,它的一個重要特征就是函數聲明提升(function declaration hoisting),意思是在執行代碼之前會先讀取函數聲明。這就意味著可以把函數聲明放在調用它的語句后面。

sayName(); // "Shaw"

function sayName(){
    console.log("Shaw");
}

這個例子不會拋出錯誤,因為在代碼執行之前會先讀取函數聲明

第二種創建函數的方式是使用函數表達式。

函數表達式有幾種不同的語法形式。
下面是最常見的一種形式。

var functionName =  function(arg0, arg1, arg2) {
    //functionBody
};

這種形式看起來好像是常規的變量賦值語句,即創建一個函數并將它賦值給變量functionName。

這種情況下創建的函數叫做 匿名函數(anonymous function), 因為function關鍵字后面沒有標識符。
匿名函數也叫拉姆達函數。匿名函數的name屬性是空字符竄。

函數表達式與其他表達式一樣,在使用前必須先賦值。

sayHi(); // error : sayHi is not a function
var sayHi = function(){
    console.log("Hi");
}

// var sayHi //此時sayHi是undefined
// sayHi() // error : sayHi is not a function
// sayHi = function() { console.log("Hi");}

理解函數提升的關鍵,就是理解函數聲明與函數表達式之間的區別。

能夠創建函數再賦值給變量,也就能夠把函數作為其他函數的值返回。

function createComparisonFunction(propertyName) {

    return function(object1, object2) {

        var value1 = object1[propertyName];
        var value2 = object2[propertyName];

        if(value1 < value2) {
            return -1
        }else if(value1 > value2) {
            return 1;
        } else {
            return 0;
        }
    }
}

createComparisonFunction()返回了一個匿名函數。
返回的函數可能會被賦值給一個變量, 或者以其他方式被調用。
不過,在createComparisonFunction()函數內部,它是匿名的。
在把函數當成值使用的情況下,都可以使用匿名函數。
不過,這并不是匿名函數唯一的用途。

遞歸

遞歸函數就是一個函數通過函數名調用自身的情況下構成的。

function factorial(num) {
    if(num <= 1) {
        return 1;
    } else {
        return num * factorial(num-1);
    }
}

factorial(4); // 4*3*2*1 = 24

//4* factorial(3) => 4*3*factorial(2) => 4*3*2*factorial(1) => 4*3*2*1 => 24

這是一個經典的遞歸階乘函數。雖然這個函數表面看來沒什么問題,但下面的代碼卻可能導致它出錯。

function factorial(num) {
    if(num <= 1) {
        return 1;
    } else {
        return num * factorial(num-1);
    }
}

var anotherFactorial = factorial;
factorial = null;
//注意這里,其實函數factorial指向一個空對象。
console.log(anotherFactorial(4));  //Error: anotherFactorial is not a function

以上代碼先把factorial()函數保存在變量anotherFactorial中,然后將factorial變量設置為null,結果指向原始函數的引用只剩下一個。
但在接下來調用anotherFactorial()時,必須執行factorial(),而factorial已經不是函數, 所以就會導致錯誤。

Google Chrome測試了上述代碼,是不行的, 建議不用深入了解這部分的內容。
在這種情況下,使用arguments.callee可以解決這個問題。

arguments.callee是一個指向正在執行的函數的指針,因此可以用它來實現對函數的遞歸調用。

function factorial(num) {
    if(num <= 1) {
        return 1;
    } else {
        return num * arguments.callee(num-1);
    }
}

“return num * arguments.callee(num-1);” 通過使用arguments.callee代替函數名,可以確保無論怎么調用函數都不出問題。
因此,在編寫遞歸函數時,使用arguments.callee總比使用函數名更保險。

但在嚴格模式下,不能通過腳本訪問arguments.callee, 訪問這個屬性會導致錯誤。

不過我們可以使用命名函數表達式來達成相同的成果。

var factorial = function f(num){
    if(num <= 1) {
        return 1;
    } else {
        return num * f(num-1);
    }
}

//factorial 指向了函數f

var anotherFactorial = factorial;
//anotherFactorial 指向了函數f

factorial = null;
//factorial 指向了一個空對象。

anotherFactorial(4); //24
////anotherFactorial 指向了函數f, 所以還可以正常調用。

以上代碼創建了創建了一個名為f()的命名函數表達式,然后將它賦值給變量factorial。
即便把函數賦值給另一個變量,函數的名字f仍然有效,所以遞歸調用照樣能正確完成。
這種方式在嚴格模式和非嚴格模式下都行得通。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/98684.html

相關文章

  • Javascript 中 Y 組合子推導

    摘要:組合子是演算中的一個概念,是任意函數的不動點,在函數式編程中主要作用是提供一種匿名函數的遞歸方式。組合子如下本文將盡量通俗易懂的以實現匿名函數遞歸為導向,推導出這一式子。若將替換為,將導致組合子中的作為的參數被立即求值。 Y 組合子是 lambda 演算中的一個概念,是任意函數的不動點,在函數式編程中主要作用是 提供一種匿名函數的遞歸方式。 Y 組合子如下: $$ λf.(λx.f(x...

    sourcenode 評論0 收藏0
  • 深入淺出JS對象屬性

    摘要:布爾值,是否能通過循環或返回屬性。而區別在于為布爾值的特征的默認值,通過屬性訪問器設置的默認都是,而通過定義屬性設置的默認都是。該方法返回被凍結的對象。 可能很多人都知道最近很火的MVVM(model-view-virtualModel)框架,如Vue/Angular/React,如果你不知道的話,就要抓緊學習了,它能夠把你從高頻復雜的DOM解析中解脫出來。MVVM框架的最主要的特性就...

    Carl 評論0 收藏0
  • ES6函數與Lambda演算

    摘要:高階函數函數式編程中,接受函數作為參數,或者返回一個函數作為結果的函數通常就被稱為高階函數。均屬于高階函數,高階函數并不神秘,我們日常編程也會用到。參考演算函數式編程指南入門康托爾哥德爾圖靈永恒的金色對角線原文函數與演算 緣起 造了一個輪子,根據GitHub項目地址,生成項目目錄樹,直觀的展現項目結構,以便于介紹項目。歡迎Star。 repository-tree 技術棧: ES6 ...

    fasss 評論0 收藏0
  • js函數學習

    摘要:函數聲明靜態函數函數聲明有個特征就是函數可以函數聲明提前函數表達式這種方式命名,沒有函數聲明提前,這個方式也是自己比較喜歡用的方式。 函數聲明(靜態函數) 函數聲明有個特征就是函數可以函數聲明提前 hello(); function hello(){ console.log(hello js); } 函數表達式(Function expressions) var hello2...

    JasinYip 評論0 收藏0
  • SICP Python 描述 3.2 函數所生成過程

    摘要:函數和所生成的過程來源譯者飛龍協議函數是計算過程的局部演化模式。在這一章中,我們會檢測一些用于簡單函數所生成過程的通用模型。也就是說,遞歸函數的執行過程可能需要再次調用這個函數。 3.2 函數和所生成的過程 來源:3.2 Functions and the Processes They Generate 譯者:飛龍 協議:CC BY-NC-SA 4.0 函數是計算過程的局部演化...

    lolomaco 評論0 收藏0

發表評論

0條評論

mudiyouyou

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<