📜  JS++ |职能

📅  最后修改于: 2022-05-13 01:54:22.964000             🧑  作者: Mango

JS++ |职能

函数是一段代码,其中包含一组指令,其中指令描述了如何完成特定任务。函数被声明,然后可以被调用一次或多次。声明函数涉及指定函数将包含的指令。当一个函数被调用时,它会执行那些指令。函数通常是计算机编程的基础,它们在 JS++ 中起着核心作用。

注意:本教程不涉及 JS++ 中的外部函数。使用function关键字声明外部函数并返回外部类型。我们将在第 9 章中研究外部函数和外部类型。(为了预览,外部类型是一种不是 JS++ 类型的类型;通常,这些是 JavaScript 类型。)本教程将研究内部 JS++ 函数。内部函数不使用function关键字声明,并且可以返回任何类型。

声明和调用函数

在我们可以使用函数做任何事情之前,我们必须声明它。因此,让我们先来看看函数是如何声明的。创建一个新文件夹并将其命名为“Functions”。然后创建一个新文件并将其命名为“Functions.jspp”。编写以下代码:

external $;

string getFavoriteAnimalString(string animal) {
    return "My favorite animal is the " + animal;
}

将 Functions.jspp 保存到 Functions 文件夹。我们编写的代码声明了一个名为getFavoriteAnimalString的函数。这个名字是合适的,因为该函数的目的是返回一个字符串,它表明一个人最喜欢的动物。该任务由函数体(大括号内的部分)中的 return 语句完成:return 语句计算return关键字右侧的表达式,然后将计算后的表达式发送回函数的调用者(它可能例如,分配给变量)。由于getFavoriteAnimalString的目的是返回一个字符串,我们可以说函数的返回类型string ,我们通过在函数名的左边写string来指定它。

就像getFavoriteAnimalString的输出将是一个字符串一样,它也需要一个字符串输入。为了组成报告一个人最喜欢的动物的字符串,该函数需要知道哪个特定动物是一个人最喜欢的。它通过名为animal的字符串参数接收此输入信息,我们将其写入函数名称右侧的括号内。当在我们程序的后期我们调用getFavoriteAnimalString来让它执行时,我们会将一个特定的字符串传递给它的输入参数:我们传递给它的特定字符串将是函数的参数

注意:函数的参数和它的参数之间的区别可能会令人困惑。澄清一下,参数是在声明函数时写入的变量。参数类型指定函数采用什么类型的输入。相比之下,参数是调用函数时作为输入传递给函数的实际值。参数成为参数变量的值。

在调用getFavoriteAnimalString之前,让我们设置一个 HTML 文档,我们将使用它来显示结果。创建第二个名为“Functions.html”的文件并写入以下内容:


Functions program

将 Functions.html 保存到您的 Functions 文件夹。现在回到 Functions.jspp 并在声明getFavoriteAnimalString的代码下方编写以下内容:

string favoriteAnimalString = getFavoriteAnimalString("cat");
$("#content").text(favoriteAnimalString);

在这些新行的第一行,我们调用getFavoriteAnimalString ,将字符串“cat”作为参数传递给它。这个函数调用返回字符串“我最喜欢的动物是猫”,我们将这个字符串分配给变量favoriteAnimalString 。在第二行,我们使用 jQuery 选择 Functions.html 的“content”元素,并将其文本设置为favoriteAnimalString的值。编译 Functions.jspp,然后在浏览器中打开 Functions.html。如果一切正常,您的文档应该显示“我最喜欢的动物是猫”。

从函数返回

在我们的示例中, getFavoriteAnimalString返回一个字符串。然而,一般来说,JS++函数可以返回任何有效类型,只要返回的值属于声明中函数名称左侧指定的返回类型。

一个函数不能有多个返回类型,但它根本不需要返回任何东西。如果函数不返回任何内容,则应使用void关键字声明它:

void displayFavoriteAnimalString(string animal) {
    string favoriteAnimalString = "My favorite animal is the " + animal;
    $("#content").text(favoriteAnimalString);
}

一个void函数可以不使用 return 语句来声明(如上例所示),也可以使用return语句来声明;它不评估或返回任何表达式。

当函数执行 return 语句时,它会立即退出。这意味着在 return 语句之后编写的任何代码都不会执行。

参数

函数可以采用零个、一个或多个参数。如果一个函数有多个参数,那么这些参数可以是相同类型或不同类型:

void displayFavoriteAnimalIfLucky(string animal, int number) {
    string favoriteAnimalString = "My favorite animal is the " + animal;
    if(number == 7){
        $("#content").text(favoriteAnimalString);
    }
}

注意:函数也可以采用可变参数,这允许函数为单个参数采用无限多个参数。完全理解可变参数需要理解数组,但是,直到下一个教程才会涉及到。因此,我们将推迟对可变参数的讨论,直到那时。

递归函数

递归函数是可以在执行期间调用自身的函数。这是递归函数的一个著名示例:

int factorial (int input) {
    if (input <= 1) {
        return input;
    } else {
        return input * factorial(input - 1);
    }
}

factorial的目的是计算并返回input参数的阶乘。例如,如果我们使用input 5 调用factorial ,它将返回 120。

factorial说明了许多递归函数共有的一般结构。该函数处理两种情况的方式不同,具体取决于输入参数的值。在基本情况下,参数的值意味着函数的任务可以很容易地完成,只需很少或不需要进一步的工作。因此,该函数无需调用自身即可返回。相比之下,在递归情况下,需要大量的进一步工作。为了实现这一点,该函数以某种方式简化或减少了进一步的工作,其中涉及使用修改后的输入值调用自身。修改后的输入值将更接近符合基本情况所需的值。

input参数小于或等于 1 时, factorial的基本情况出现。在这种情况下,函数只返回input 。相反,如果input大于 1,则函数返回input * factorial(input - 1) 。因此, factorial将重复调用自身,每次递归调用时input的值减 1。当factorialinput值 1 调用自身时,该特定的递归调用返回,然后使之前的每个递归调用都返回。

递归函数应谨慎使用。特别是,确保每次递归调用时,输入参数的值更接近基本情况所需的值,这一点很重要。如果你不这样做,就有可能创建无限递归的危险:这将导致运行时错误。此外,使用迭代函数(即使用循环的函数)通常比递归更有效。当使用递归有好处时,它通常在于使代码更易于阅读,而不是提高计算效率。

重载

JS++ 允许函数重载。重载包括声明两个具有相同名称但具有不同参数列表的函数。例如,我们可以重载一个名为displayFavoriteAnimalString的函数,如下所示:

编译器允许您以这种方式声明两个具有相同名称的函数,因为它们的参数列表不同:第一个函数采用单个字符串参数,而第二个函数采用两个。这种差异意味着当您调用两个函数中的一个时,它的含义没有歧义:如果您提供一个字符串参数,那么它必须是第一个函数,如果您提供两个字符串参数,那么它必须是第二个.

在给出的示例中,两个重载函数具有相同的返回类型:void。但是,这不是必需的。只要重载函数有不同的参数列表,它们的返回类型可以相同也可以不同。但是,您不能重载具有相同参数列表和不同返回类型的函数:这会导致调用者所指的函数不明确,因此编译器不会允许这样做。

当重载函数执行概念上相似的角色时,重载可能很有意义,从调用者的角度来看,这种相似性应该是显而易见的。当重载函数在概念上扮演不同的角色时,不应使用重载,因为这会使您的代码更难理解。如果可能,要避免的一种特殊技术是为重载函数提供不同的返回类型:这不被认为是好的编码风格。

回调和函数表达式

考虑以下代码:

external $;
int(int, int) processNumbers = int(int a, int b) {
    return a + b;
};

如果您仔细查看此语法(并注意结尾的分号!),您会发现它不是函数声明的正常语法。相反,我们这里有一个变量赋值。该变量名为processNumbers ,其类型由名称左侧的代码指定: int(int, int) 。这是一个回调类型。这种类型的变量可以将函数作为其值。但是,变量可以采用的函数范围仅限于参数和返回类型与回调类型指定的函数匹配的函数。因此,鉴于processNumbers具有回调类型int(int, int) ,只有当它接受两个int参数并返回一个int时,才能将函数分配给processNumbers

“=”号右侧的代码将函数表达式分配给进程号。函数表达式与函数声明的不同之处在于它的计算结果为一个值(表示的函数)。这意味着函数表达式可以在变量赋值中使用(如此处),或作为参数传递给另一个函数,或从另一个函数返回。

分配给processNumbers的函数是一个加法函数。它将两个int参数相加并返回结果。赋值很好,因为加法函数具有由变量的回调类型指定的参数和返回类型:它接受两个int参数并返回一个int 。现在我们可以调用processNumbers

int result = processNumbers(3, 4);
$("#content").text(result);

然而,稍后在我们的程序中,我们可能决定为processNumbers分配一个不同的函数:

processNumbers = int(int a, int b) {
    return a * b;
};

这个赋值和前一个一样有效,因为赋值的乘法函数也有正确的参数和返回类型:它接受两个int参数并返回一个int 。如果我们在将这个新函数分配给它之后调用processNumbers ,结果将与我们之前调用返回的结果不同。