WaterNorth's Blog

09函数

7 分钟WaterNorth

一、函数声明 #

使用 函数声明 创建函数。

function 关键字首先出现,然后是 函数名,然后是括号之间的 参数 列表(用逗号分隔,在上述示例中为空,我们将在接下来的示例中看到),最后是花括号之间的代码(即“函数体”)。

function name(parameter1, parameter2, ... parameterN) {
  ...body...
}

二、变量 #

在函数中声明的变量只在该函数内部可见,函数也可以访问外部变量。

函数对外部变量拥有全部的访问权限。函数也可以修改外部变量。

只有在没有局部变量的情况下才会使用外部变量。

如果在函数内部声明了同名变量,那么函数会 遮蔽 外部变量。例如,在下面的代码中,函数使用局部的 userName,而外部变量被忽略:

let userName = 'John';

function showMessage() {
  let userName = "Bob"; // 声明一个局部变量

  let message = 'Hello, ' + userName; // Bob
  alert(message);
}

// 函数会创建并使用它自己的 userName
showMessage();

alert( userName ); // John,未被更改,函数没有访问外部变量。

任何函数之外声明的变量,例如上述代码中的外部变量 userName,都被称为 全局 变量。

全局变量在任意函数中都是可见的(除非被局部变量遮蔽)。

减少全局变量的使用是一种很好的做法。现代的代码有很少甚至没有全局变量。大多数变量存在于它们的函数中。但是有时候,全局变量能够用于存储项目级别的数据。

三、参数 #

我们可以通过参数将任意数据传递给函数。

这里还有一个例子:我们有一个变量 from,并将它传递给函数。请注意:函数会修改 from,但在函数外部看不到更改,因为函数修改的是复制的变量值副本:

function showMessage(from, text) {

  from = '*' + from + '*'; // 让 "from" 看起来更优雅

  alert( from + ': ' + text );
}

let from = "Ann";

showMessage(from, "Hello"); // *Ann*: Hello

// "from" 值相同,函数修改了一个局部的副本。
alert( from ); // Ann

如果一个函数被调用,但有参数(argument)未被提供,那么相应的值就会变成 undefined

我们可以使用 = 为函数声明中的参数指定所谓的“默认”(如果对应参数的值未被传递则使用)值:

function showMessage(from, text = "no text given") {
  alert( from + ": " + text );
}

showMessage("Ann"); // Ann: no text given

现在如果 text 参数未被传递,它将会得到值 "no text given"

这里 "no text given" 是一个字符串,但它可以是更复杂的表达式,并且只会在缺少参数时才会被计算和分配。所以,这也是可能的:

function showMessage(from, text = anotherFunction()) {
  // anotherFunction() 仅在没有给定 text 时执行
  // 其运行结果将成为 text 的值
}

有些时候,将参数默认值的设置放在函数执行(相较更后期)而不是函数声明时,也行得通。

我们可以通过将参数与 undefined 进行比较,来检查该参数是否在函数执行期间被传递进来:

function showMessage(text) {
  // ...

  if (text === undefined) { // 如果参数未被传递进来
    text = 'empty message';
  }

  alert(text);
}

showMessage(); // empty message

……或者我们可以使用 || 运算符:

function showMessage(text) {
  // 如果 text 为 undefined 或者为假值,那么将其赋值为 'empty'
  text = text || 'empty';
  ...
}

现代 JavaScript 引擎支持空值合并运算符??,它在大多数假值(例如 0)应该被视为“正常值”时更具优势:

function showCount(count) {
  // 如果 count 为 undefined 或 null,则提示 "unknown"
  alert(count ?? "unknown");
}

showCount(0); // 0
showCount(null); // unknown
showCount(); // unknown

四、返回值 #

函数可以将一个值返回到调用代码中作为结果。

指令 return 可以在函数的任意位置。当执行到达时,函数停止,并将值返回给调用代码(分配给上述代码中的 result)。

只使用 return 但没有返回值也是可行的。但这会导致函数立即退出。

例如:

function showMovie(age) {
  if ( !checkAge(age) ) {
    return;
  }

  alert( "Showing you the movie" ); // (*)
  // ...
}

在上述代码中,如果 checkAge(age) 返回 false,那么 showMovie 将不会运行到 alert

空值的 return 或没有 return 的函数返回值为 undefined

五、函数命名 #

函数就是行为(action)。所以它们的名字通常是动词。它应该简短且尽可能准确地描述函数的作用。这样读代码的人就能清楚地知道这个函数的功能。

一种普遍的做法是用动词前缀来开始一个函数,这个前缀模糊地描述了这个行为。团队内部必须就前缀的含义达成一致。

例如,以 "show" 开头的函数通常会显示某些内容。

函数以 XX 开始……

  • "get…" —— 返回一个值,
  • "calc…" —— 计算某些内容,
  • "create…" —— 创建某些内容,
  • "check…" —— 检查某些内容并返回 boolean 值,等。

这类名字的示例:

showMessage(..)     // 显示信息
getAge(..)          // 返回 age(gets it somehow)
calcSum(..)         // 计算求和并返回结果
createForm(..)      // 创建表单(通常会返回它)
checkPermission(..) // 检查权限并返回 true/false

评论

0

评论功能待配置数据库后启用。