共计 6687 个字符,预计需要花费 17 分钟才能阅读完成。
在 Construct 中学习 JavaScript,第 5 部分:函数
这是教程系列的第 5 部分在 Construct 中学习 JavaScript. 本部分从第 4 部分继续。因此,如果您错过了它,请参阅在 Construct 中学习 JavaScript,第 4 部分:控制流.
在这一部分中,我们将继续使用脚本文件,而不是在事件表中使用脚本块。这将演示如何在 Construct 中使用脚本文件,脚本文件还提供了一个更方便的地方来编写更长的代码段。
使用脚本文件
让我们重新开始这部分。如果已打开现有项目,请关闭现有项目,然后再次在 Construct 中创建一个新的空项目。
在“项目栏”中,右键单击“脚本”文件夹,然后单击“添加脚本”。
将脚本文件添加到项目中
这会将新的脚本文件添加到您的项目中。将打开一个使用完整中间视图的代码编辑器,因为我们不再涉及事件表。
Construct 添加的第一个脚本文件包含一些默认代码,旨在帮助更轻松地将代码与 Construct 集成。但是,我们不需要这个。因此,请选择所有代码并将其删除。您现在应该看到一个空的代码编辑器。
以前,我们使用 JavaScript 代码来代替事件表中的操作。这意味着只要事件块运行,例如在布局开始时或单击按钮时,它就会运行代码。现在我们使用的是脚本文件,所有顶级代码都将在页面加载时立即自动运行。这实际上是在 Construct 开始运行项目之前,但就本指南而言,这并不重要。
您可以通过在脚本文件中再次输入我们的第一行代码来检查这是否有效:
console.log("Hello world!");
预览项目并检查浏览器控制台,您将看到消息出现。
现在,此代码甚至在 Construct 开始运行项目之前就运行,并且 Construct 在开始运行项目时会记录一些消息。因此,您可能会看到控制台消息现在出现在 Construct 记录的其他消息之间。不过这并不重要 – 和以前一样,您可以忽略其他控制台消息。
现在,我们已经转向使用脚本文件。因此,从现在开始,应将本指南中的代码示例输入到脚本文件的代码编辑器中。
功能
功能是所有计算机编程的另一个重要部分。函数本质上是一组可以在多个位置重复使用的语句。它们也是确保代码组织良好、程序的每个关键任务都有不同功能的好方法。
如果您在 Construct 的事件表中使用过功能块,那么原理是相似的。
声明函数
在 JavaScript 中,函数可以像这样声明:
function logMessage()
{
console.log("Hello world!");
}
这将创建一个名为 logMessage 的函数,该函数会将 Hello world!记录到控制台。就其本身而言,此代码实际上并未执行任何操作。它只是声明该函数在那里,但实际上还没有使用它。
调用函数
要在函数内部运行语句,我们需要调用该函数。这是使用其名称后跟括号完成的。尝试以下代码片段,它添加对函数的调用。()
// Declare function
function logMessage()
{
console.log("Hello world!");
}
// Call the function
logMessage();
现在这会将 Hello world!记录到控制台,因为我们都声明了函数(描述它的作用),并调用了它(实际运行它)。
此函数可以在多个位置调用,这样就不必到处重复函数内的所有代码。在这种情况下,这似乎是一个小的节省,但真正的程序可能具有漫长而复杂的功能,使其成为更大的节省。
注意:如果您重复记录完全相同的控制台消息,许多浏览器控制台将避免重复,而只是在消息旁边添加一个数字,指示重复的次数。如果你打电话两次,你会注意到这一点。为了避免这会导致任何混淆,本指南将确保所有代码示例始终记录不同的消息。logMessage()
参数
函数也可以是参数,这些参数是函数体可以使用的附加值。它们位于括号之间,用逗号分隔。我们之前使用的代码实际上意味着“无参数”。以下代码声明一个函数,该函数使用两个参数来表示要在日志消息中显示的两个数字,然后使用不同的参数值调用该函数两次。()()
// Declare function with two parameters
function logNumbers(firstNumber, secondNumber)
{
console.log(The first number is ${firstNumber} and the second number is ${secondNumber}
);
}
// Call the function twice with different parameters
logNumbers(3, 4);
logNumbers(6, 7);
这将记录两条消息:
第一个数字是 3,第二个数字是 4
第一个数字是 6,第二个数字是 7
请注意在调用中传递的值(例如 in 中的 3 和 4)是如何传递给相应的参数和函数 logNumbers 的。然后,它使用提供的值在函数内部运行代码。logNumbers(3, 4)firstNumbersecondNumber
在函数 logNumbers 中,参数 和 本质上是变量,但不需要声明 – 在声明函数参数时,只需名称即可。firstNumbersecondNumberlet
范围
现在是时候涵盖变量的另一个方面了:范围。这是指在 JavaScript 代码中可以引用变量的位置。这取决于变量的声明位置。
可以调整 logNumbers 函数,以在函数内部使用消息的变量:
function logNumbers(firstNumber, secondNumber)
{
let message = The first number is ${firstNumber} and the second number is ${secondNumber}
;
console.log(message);
}
变量 message 的作用域为函数 logNumbers。换句话说,它只能在该函数内部使用。它不能在该功能之外使用,因为它超出了其范围 – 它实际上在其他任何地方都不存在。
演示这一点的一种方法是尝试访问函数外部的消息。请注意错误如何声明未定义消息。
function logNumbers(firstNumber, secondNumber)
{
let message = The first number is ${firstNumber} and the second number is ${secondNumber}
;
console.log(message);
}
// ReferenceError: message is not defined
console.log(message);
如果您使用此代码预览项目,Construct 将显示一个提示,通知您运行主脚本时发生错误。这是意料之中的 – 我们输入了一些无效的代码。关闭提示,然后像往常一样打开浏览器控制台以查看错误消息。
这同样适用于函数参数 firstNumber 和 secondNumber:它们只能在函数体中访问。
这同样适用于在 ‘if’ 语句以及 ‘while’ 和 ‘for’ 循环中声明的变量。基本上,无论您在哪里看到大括号和,其中声明的任何变量都只能在该范围内访问,因为大括号定义了一个新的范围。{}
循环中的作用域
一个小例外是,作为“for”循环的一部分声明的变量也可以在大括号内部和大括号之间访问,但在大括号之外的任何地方都可以访问:for (…)
// ‘i’ cannot be used here
// ‘i’ can be used inside for (…)
for (let i = 0; i < 10; i++)
{
// ‘i’ can be used here
}
// ‘i’ cannot be used here
与等效的“while”循环相比,这使变量的范围减小了:
// ‘i’ cannot be used here (prior to its declaration)
let i = 0;
// ‘i’ can be used here
while (i < 10)
{
// ‘i’ can be used here
i++
}
// ‘i’ can be used here
这实际上是 ‘for’ 循环的一个有用方面,因为它确保循环变量对于循环是唯一的。
内部范围
虽然变量不能在其作用域之外使用,但它们可以在其作用域内的任何地方使用。证明这一点的一种方法是,函数可以引用在函数外部声明的变量。
let message = "Hello world!";
function logMessage()
{
// OK: ‘message’ is still in scope
console.log(message);
}
logMessage();
变量仍位于其自身作用域内的任何嵌套大括号内的作用域内。它只是尝试访问其范围之外的变量,从而导致错误。
顶级范围
在脚本文件的“顶层”声明的变量,即不在任何大括号内,就像上一个示例中的 message 一样,其范围限定为整个文件。如果添加另一个脚本文件,则无法在此处访问该变量,因为其他文件超出了顶级变量的范围。
请注意,顶级范围在其他 JavaScript 环境中的工作方式可能有所不同。Construct 使用现代“模块”脚本,其中顶级范围以这种方式工作。但是,如果其他工具或环境使用较旧的“经典”脚本,则顶级范围实际上是全局范围,因此可以跨不同的文件使用顶级变量。尽管这在 Construct 中不会发生,但它在行业的其他部分仍然很常见,因此值得注意的是,这在其他地方可能会有所不同。
函数也有范围
函数的范围也限定为声明它们的位置。再次引用前面的示例,logMessage 函数在顶层声明,因此可以在该脚本文件内的任何位置使用,但不能在其他脚本文件中使用。
为了演示函数的范围,请尝试以下代码示例:
function logMessageOuter()
{
function logMessageInner()
{
console.log("Hello world!");
}
logMessageInner();
}
// ‘logMessageInner’ is not accessible here
logMessageOuter();
这声明了一个嵌套函数,或另一个函数内部的函数。logMessageInner 只能在函数 logMessageOuter 中使用,不能在函数外部使用。该函数的作用域与在 logMessageOuter 中声明的变量相同。
总结
作用域是变量声明、函数声明和函数参数的一个重要方面,它定义了它们可以在何处使用。简而言之,每一对大括号都定义了一个新的范围,而任何大括号内之外的任何东西都位于顶层。在特定作用域中声明的内容可以在该作用域内的任何位置使用,包括内部作用域,但不能在该作用域之外使用。在处理函数时,范围成为一个重要的特性,这就是为什么我们现在稍微绕道来涵盖它。{}
这些关于范围的规则有助于保持代码的组织性,因为它可以防止在它们应该使用的地方之外意外使用事物。它通常也消除了担心名称是否在大型程序中的其他地方使用的需要,因为您只需要考虑特定代码段的范围。
如果将顶级函数和变量显式放置在全局范围内,或者导出和导入它们,则可以在其他脚本文件中使用顶级函数和变量,但这些是我们稍后将在本指南中介绍的更高级的主题。
返回值
函数的另一个有用部分是它们可以使用语句返回一个值,如以下示例所示。return
function add(a, b)
{
return a + b;
}
console.log(add(4, 5)); // 9
add 函数将其两个参数相加,然后返回它。这将成为调用函数 at 返回的值,因此数字 9 将记录到控制台。add(4, 5)
函数可以返回任何类型的值,例如数字、字符串或布尔值。由于 JavaScript 是动态类型的,函数甚至可以在不同的情况下返回不同的类型,例如“if”语句中的字符串和“else”语句中的数字 – 但通常建议确保函数始终返回相同的类型,以确保它们可预测地工作。
类似于 in 循环或 switch 语句,也会提前退出函数,因此函数中的它之后不会运行任何代码。breakreturn
function add(a, b)
{
return a + b;
// no code here will run, as 'return'
// also exits the function
}
您还可以有条件地提前退出函数,例如在“if”语句中返回。
function divide(a, b)
{
if (b === 0)
{
// Log a warning message
console.log("Dividing by zero!");
// Return 0 instead of Infinity or NaN
return 0;
}
// This only runs if it did not already return
return a / b;
}
console.log(divide(1, 0));
即使函数不需要返回值,它们仍然可以用于提前退出 – 在这种情况下,没有值的函数本身将直接退出函数。(如果有任何内容尝试使用返回值,它将获得 .)returnreturn;undefined
如果您在 Construct 的事件表中使用了返回值的函数块,请注意 Set return value 操作不会像在 JavaScript 中那样提前退出函数。
返回后不要添加换行符
使用 时需要注意一个重要的陷阱。回到第 2 部分,我们注意到您通常可以省略分号,JavaScript 会猜测它们应该去哪里。在第 4 部分中,我们还介绍了 JavaScript 通常如何不关心空格或换行符的位置。但是,如果换行符紧随其后,JavaScript 总是猜测分号紧随其后。这通常是一个错误的猜测,通常被认为是一个设计错误,但现在改变它为时已晚,所以我们只能忍受它。returnreturnreturn
以下代码片段演示了无法按预期工作的代码。
function add(firstValue, secondValue, thirdValue)
{
// OOPS: line break after ‘return’
return
firstValue + secondValue + thirdValue;
}
在这种情况下,JavaScript 会错误地猜测分号在后面。然后,在返回语句之后不运行任何内容。所以它相当于写这个:return
function add(firstValue, secondValue, thirdValue)
{
return;
}
不提供返回值的函数返回。因此,您可能认为该函数会返回一个包含三个值之和的数字,但相反,它返回,只是因为 之后有一个换行符。这是自动插入分号被视为错误的原因之一。undefinedundefinedreturn
因此,这里的教训是永远不要在语句后使用换行符。请改用如下代码。return
function add(firstValue, secondValue, thirdValue)
{
// OK: no line break after ‘return’
return firstValue + secondValue + thirdValue;
}
一些例子
祝贺!您现在已经学会了足够的 JavaScript,我们可以编写一些有用的小程序。为了使示例简单,让我们编写一些可以列出特定数字的代码。
列出偶数
下面是一些代码,可以将所有偶数(最多 50)记录到控制台。
function isEven(n)
{
return n % 2 === 0;
}
for (let i = 1; i < 50; i++)
{
if (isEven(i))
{
console.log(Number ${i} is even
);
}
}
函数 isEven 返回一个布尔值(true 或 false),指示参数是否为偶数。它使用余数运算符进行此检查:如果数字除以 2 的余数为零,则它是 2 的倍数,因此是偶数。n%
然后使用“for”循环对 1 到 50 的每个数字调用此函数。请注意,它是在“if”语句中调用的,因此,如果函数返回 true,则“if”语句中的代码将运行,并且该代码将该数字记录到控制台,声明它是一个偶数。
列出质数
一个素数是一个只有自身和 1 作为因数的数字,或者换句话说,除了它自身和 1 之外,没有两个整数相乘得出该数字。
检查一个数是否为质数的一个简单方法是检查它是否是从 2 到的平方根的任何数字的倍数。这也可以通过“for”循环来完成。这里有一些代码,将记录从 1 到 100 的每个质数。nn
function isPrime(n)
{
// 1 is not a prime number
if (n === 1)
return false;
// Raise to power of 1/2 takes square root
let sqrtN = n ** 0.5;
// Check for factors from 2 to square root of n
for (let f = 2; f <= sqrtN; f++)
{if (n % f === 0)
{
// Found a factor: not a prime
return false;
}
}
// Did not find any factors: is a prime
return true;
}
for (let i = 1; i < 100; i++)
{
if (isPrime(i))
{
console.log(Number ${i} is prime
);
}
}
这结合了我们迄今为止学到的许多东西。以下是有关 isPrime 函数工作原理的一些注意事项:
1 不是质数,但该函数将返回 true,因此我们必须为它设置一个例外。因此,该函数首先检查数字是否为 1,如果是,则提前退出,返回 false。
提高到一半的幂计算一个数字的平方根。这也可以用来代替(但本指南还没有涵盖任何 JavaScript 的内置数学函数)。Math.sqrt(n)n ** 0.5
然后,“for”循环检查从 2 到数字的平方根(包括数字的平方根)的每个数字。请注意,循环从变量 2 开始,只要它小于或等于,它就会递增,这确保当它是整数时,它还会检查是否为因子。fsqrtNsqrtN
与检查 isEven 类似,我们可以检查是否是使用余数运算符的一个因素,并检查余数是否为零。在这种情况下是 的倍数,因此不是素数,因此函数返回 false。fnnfn
如果整个 'for' 循环运行而不返回,则表示它没有找到 的任何因数。因此是素数,因此函数返回 true。nn
然后,与前面的示例类似,使用“for”循环来检查从 1 到 100 的每个数字,看看它是否是质数,如果是,则向控制台记录一条消息。
如果您想进一步练习到目前为止所学的知识,请尝试编写更多函数来测试不同类型的数字,例如平方数,并列出 1-100 中满足测试的所有数字。提示:您可以使用 来测试一个数字是否为整数,因为在 JavaScript 中,余数运算符处理分数,因此如果余数除以 1 为 0,则该数字没有小数部分,因此是整数。然后,您可以测试诸如数字的平方根是否为整数之类的事情,这告诉您该数字是否为平方数。n % 1 === 0
结论
在这一部分中,我们介绍了:
在 Construct 中使用脚本文件
声明函数
调用函数
使用函数参数
变量、参数和函数的范围
从函数返回值
为什么要避免在以下之后换行 return
一些示例将到目前为止涵盖的所有内容结合起来,以列出具有某些数学属性的数字
JavaScript 中的函数还有很多内容,因此本指南的下一部分将介绍函数的更多方面。
了解更多信息
如果你想更深入地挖掘,你可以在以下 MDN Web Docs 链接中了解更多关于本指南中提到的功能。
函数声明
范围
返回陈述
第 6 部分
当您准备好继续时,请继续阅读下一部分,网址为在 Construct 中学习 JavaScript,第 6 部分:有关函数的更多信息!