JavaScript之函数

JavaScript函数相关的知识文档可以参考来自印记中文的译文:函数 (javascript.info)

这里我挑选一些容易犯错的点

变量作用域

JavaScript函数中的变量分为局部变量外部变量,局部变量声明在函数体内部,生命周期也在函数体内部,外部变量在整个JavaScript文件中适用。

局部变量

在函数中声明的变量只在该函数内部可见。

例如:

 function showMessage() {
   let message = "Hello, I'm JavaScript!"; // 局部变量
 ​
   alert( message );
 }
 ​
 showMessage(); // Hello, I'm JavaScript!
 ​
 alert( message ); // <-- 错误!变量是函数的局部变量

外部变量

函数也可以访问外部变量,例如:

let userName = 'John';
 ​
 function showMessage() {
   let message = 'Hello, ' + userName;
   alert(message);
 }
 ​
 showMessage(); // Hello, John

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

例如:

 let userName = 'John';
 ​
 function showMessage() {
   userName = "Bob"; // (1) 改变外部变量
 ​
   let message = 'Hello, ' + userName;
   alert(message);
 }
 ​
 alert( userName ); // John 在函数调用之前
 ​
 showMessage();
 ​
 alert( userName ); // Bob,值被函数修改了

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

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

 let userName = 'John';
 ​
 function showMessage() {
   let userName = "Bob"; // 声明一个局部变量
 ​
   let message = 'Hello, ' + userName; // Bob
   alert(message);
 }
 ​
 // 函数会创建并使用它自己的 userName
 showMessage();
 ​
 alert( userName ); // John,未被更改,函数没有访问外部变量。

全局变量

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

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

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

函数的参数

当函数在 和 行中被调用时,给定值被复制到了局部变量 和 。然后函数使用它们进行计算。(*)(**)from text

这里还有一个例子:我们有一个变量 ,并将它传递给函数。请注意:函数会修改 ,但在函数外部看不到更改,因为函数修改的是复制的变量值副本: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 = anotherFunction()) {
   // anotherFunction() 仅在没有给定 text 时执行
   // 其运行结果将成为 text 的值
 }

默认参数的计算

在 JavaScript 中,每次函数在没带个别参数的情况下被调用,默认参数会被计算出来。

在上面的例子中,如果传递了参数 ,那么 就不会被调用。text``anotherFunction()

如果没传递参数 ,那么 就会被调用。text``anotherFunction()

还有一种处理方式就是在函数体中进行处理,也叫后备的默认参数

我们可以通过将参数与 进行比较,来检查该参数是否在函数执行期间被传递进来: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指令 可以在函数的任意位置。当执行到达时,函数停止,并将值返回给调用代码(分配给上述代码中的 )。return``result

在一个函数中可能会出现很多次 。例如:return

function checkAge(age) {
   if (age >= 18) {
     return true;
   } else {
     return confirm('Got a permission from the parents?');
   }
 }
 ​
 let age = prompt('How old are you?', 18);
 ​
 if ( checkAge(age) ) {
   alert( 'Access granted' );
 } else {
   alert( 'Access denied' );
 }

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

例如:

 function showMovie(age) {
   if ( !checkAge(age) ) {
     return;
   }
 ​
   alert( "Showing you the movie" ); // (*)
   // ...
 }

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

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

如果函数无返回值,它就会像返回 一样:undefined

 function doNothing() { /* 没有代码 */ }
 ​
 alert( doNothing() === undefined ); // true

空值的 和 等效:return``return undefined

 function doNothing() {
   return;
 }
 ​
 alert( doNothing() === undefined ); // true

不要在 return 与返回值之间添加新行

对于 的长表达式,可能你会很想将其放在单独一行,如下所示:return

 return
  (some + long + expression + or + whatever * f(a) + f(b))

但这不行,因为 JavaScript 默认会在 之后加上分号。上面这段代码和下面这段代码运行流程相同:return

 return;
  (some + long + expression + or + whatever * f(a) + f(b))

因此,实际上它的返回值变成了空值。

如果我们想要将返回的表达式写成跨多行的形式,那么应该在 的同一行开始写此表达式。或者至少按照如下的方式放上左括号:return

 return (
   some + long + expression
   + or +
   whatever * f(a) + f(b)
   )

然后它就能像我们预想的那样正常运行了。

总结

函数声明方式如下所示:

 function name(parameters, delimited, by, comma) {
   /* code */
 }
  • 作为参数传递给函数的值,会被复制到函数的局部变量。
  • 函数可以访问外部变量。但它只能从内到外起作用。函数外部的代码看不到函数内的局部变量。
  • 函数可以返回值。如果没有返回值,则其返回的结果是 。undefined

为了使代码简洁易懂,建议在函数中主要使用局部变量和参数,而不是外部变量。

与不获取参数但将修改外部变量作为副作用的函数相比,获取参数、使用参数并返回结果的函数更容易理解。

函数命名:

  • 函数名应该清楚地描述函数的功能。当我们在代码中看到一个函数调用时,一个好的函数名能够让我们马上知道这个函数的功能是什么,会返回什么。
  • 一个函数是一个行为,所以函数名通常是动词。
  • 目前有许多优秀的函数名前缀,如 、、、 等等。使用它们来提示函数的作用吧。create… show… get… check…

函数是脚本的主要构建块。现在我们已经介绍了基本知识,现在我们就可以开始创建和使用函数了。但这只是学习和使用函数的开始。我们将继续学习更多函数的相关知识,更深入地研究它们的先进特征。

© 版权声明
THE END
点赞12 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容