探索JavaScript函数---基础篇

2024-06-02 09:15:04 浏览数 (3)

函数

一般来说,一个函数是可以通过外部代码调用的一个“子程序”(或在递归的情况下由内部函数调用)。像程序本身一样,一个函数由称为函数体的一系列语句组成。值可以传递给一个函数,函数将返回一个值。在 JavaScript 中,函数是头等 (first-class)对象,因为它们可以像任何其他对象一样具有属性和方法,可以像其他数据类型一样被赋值给变量、作为参数传递给其他函数,甚至作为其他函数的返回值。它们与其他对象的区别在于函数可以被调用。简而言之,它们是Function对象。 ​​​​​​​ ​​​​​​​——MDN

声明和调用

函数可以把具有相同或相似逻辑的代码“包裹”起来,通过函数调用执行这些被“包裹”的代码逻辑,这么做的优势是有利于精简代码方便复用。

声明(定义)

声明(定义)一个完整函数包括关键字、函数名、形式参数、函数体、返回值5个部分

调用

声明(定义)的函数必须调用才会真正被执行,使用 () 调用函数。

代码语言:javascript复制
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>函数声明和调用</title>
</head>
<body>
  <script>
    // 声明(定义)了最简单的函数,既没有形式参数,也没有返回值
    function sayHi() {
      console.log('Hi~')
    }
    // 函数调用,这些函数体内的代码逻辑会被执行
    // 函数名()
        
    sayHi()
    // 可以重复被调用,多少次都可以
    sayHi()
  </script>
</body>
</html>

注:函数名的命名规则与变量是一致的,并且尽量保证函数名的语义。

参数

参数是在函数名后的圆括号内定义的,多个参数之间用逗号分隔。

通过向函数传递参数,可以让函数更加灵活多变,参数可以理解成是一个变量

声明(定义)一个功能为打招呼的函数

  • 传入数据列表
  • 声明这个函数需要传入几个数据
  • 多个数据用逗号隔开
代码语言:javascript复制
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>函数参数</title>
</head>
<body>
​
  <script>
    // 声明(定义)一个功能为打招呼的函数
    // function sayHi() {
    //   console.log('Hi~')
    // }
    // 调用函数
    // sayHi()
    
​
    // 这个函数似乎没有什么价值,除非能够向不同的人打招呼
    // 这就需要借助参数来实现了
    function sayHi(name) {
      // 参数 name 可以被理解成是一个变量
      console.log(name)
      console.log('Hi~'   name)
    }
​
    // 调用 sayHi 函数,括号中多了 '小明'
    // 这时相当于为参数 name 赋值了
    sayHi('小明')// 结果为 小明
​
    // 再次调用 sayHi 函数,括号中多了 '小红'
    // 这时相当于为参数 name 赋值了
    sayHi('小红') // 结果为 小红
  </script>
</body>
</html>

总结:

  1. 声明(定义)函数时的形参没有数量限制,当有多个形参时使用 , 分隔
  2. 调用函数传递的实参要与形参的顺序一致
形参和实参
形参(Formal Arguments)

形参是在定义函数时,在函数名后的括号内指定的占位符变量。它们代表函数期望接收的值,但并不实际包含值。形参的作用是告诉调用者这个函数需要哪些信息才能执行其任务。例如:

代码语言:javascript复制
function addNumbers(a, b) {
    return a   b;
}

在这个例子中,a 和 b 是形参,它们代表了将来调用该函数时需要提供的两个数值。

实参(Actual Arguments)

实参是当函数被调用时,实际传递给函数的具体值。这些值用来替换函数定义中的形参。继续上面的例子,当我们调用 addNumbers 函数时,传递的值就是实参:

代码语言:javascript复制
let result = addNumbers(5, 3);

这里,5 和 3 就是实参,它们分别对应并赋值给形参 a 和 b,函数执行后返回它们的和。

形参与实参的关系
  • 匹配:实参的数量和类型应当与函数定义中的形参相匹配。如果数量不匹配,JavaScript 在严格模式下会抛出错误;如果不使用严格模式,则可能会导致意外的行为或错误。
  • 传递方式:JavaScript 中,实参向形参的传递是基于值的传递。对于原始类型(如数字、字符串、布尔值),传递的是值的副本;而对于引用类型(如对象、数组),传递的是引用的副本,这意味着函数内部可以修改对象的属性或数组的内容,影响到外部。
  • 默认参数:ES6 引入了默认参数功能,允许在定义函数时为形参指定默认值。如果调用函数时没有提供对应的实参,就使用默认值。
代码语言:javascript复制
function greet(name = "User") {
    console.log(`Hello, ${name}!`);
}

greet(); // 输出 "Hello, User!"
greet("Alice"); // 输出 "Hello, Alice!"

eg:

代码语言:javascript复制
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>函数参数</title>
</head>
<body>
  <script>
    // 声明(定义)一个计算任意两数字和的函数
    // 形参 x 和 y 分别表示任意两个数字,它们是两个变量
    function count(x, y) {
      console.log(x   y);
    }
    // 调用函数,传入两个具体的数字做为实参
    // 此时 10 赋值给了形参 x
    // 此时 5  赋值给了形参 y
    count(10, 5); // 结果为 15
  </script>
</body>
</html>
返回值

return语句用于从函数中退出并返回一个值给调用者。如果函数体中没有return语句,或者return后面没有值,那么函数默认返回undefined

代码语言:javascript复制
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>函数返回值</title>
</head>
<body>
​
  <script>
    // 定义求和函数
    function count(a, b) {
      let s = a   b
      // s 即为 a   b 的结果
      // 通过 return 将 s 传递到外部
      return s
    }
​
    // 调用函数,如果一个函数有返回值
    // 那么可将这个返回值赋值给外部的任意变量
    let total = count(5, 12)
  </script>
</body>
</html>

总结:

  1. 在函数体中使用return 关键字能将内部的执行结果交给函数外部使用
  2. 函数内部只能出现1 次 return,并且 return 下一行代码不会再被执行,所以return 后面的数据不要换行写
  3. return会立即结束当前函数
  4. 函数可以没有return,这种情况默认返回值为 undefined
作用域

通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。

作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。

全局作用域
  • 定义:在代码的最外层定义的变量或函数拥有全局作用域,这意味着它们在整个代码中任何地方都是可访问的。
  • 特点:全局变量会一直存在,直至页面关闭,可能导致内存泄漏。尽量避免非必要地使用全局变量,因为它们容易引起命名冲突。
代码语言:javascript复制
let globalVar = "I'm global!";
function test() {
    console.log(globalVar); // 访问全局变量
}
test(); // 输出 "I'm global!"
局部作用域
  • 定义:在函数内部定义的变量拥有局部作用域,只能在该函数内部访问。
  • 特点:每次函数调用时都会创建新的局部作用域,变量在函数执行结束后会被销毁,有助于资源管理。
代码语言:javascript复制
function test() {
    let localVar = "I'm local!";
    console.log(localVar); // 访问局部变量
}
test(); // 输出 "I'm local!"
console.log(localVar); // 错误,localVar在此不可访问

注意:

  • 如果函数内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐,这种行为经常导致意料之外的错误和全局变量的污染。
  • 函数的形参(形式参数)在函数定义时自动被视为局部变量。
匿名函数

匿名函数,顾名思义,是没有名字的函数。在JavaScript中,匿名函数是一种非常灵活且常用的特性,常用于需要一次性使用的简短函数逻辑场景,或是作为其他函数的参数传递给高阶函数。

函数表达式

函数表达式将函数定义赋值给一个变量、对象的属性或作为参数传递给其他函数。它可以是命名的也可以是匿名的。

代码语言:javascript复制
// 声明
let fn = function() { 
   console.log('函数表达式')
}
// 调用
fn()

函数表达式在赋值操作完成之前不能被调用,因为它们属于普通变量的赋值,遵循变量声明的规则。

立即执行函数

立即执行函数(IIFE,Immediately Invoked Function Expression),即立即调用的函数表达式,也就是说,声明函数的同时立即调用这个函数。

代码语言:javascript复制
(function(){ xxx  })();
(function(){xxxx}());

//eg:
(function() {
    console.log("这是一个匿名函数,并且立即被执行了!");
})();

注意:

  • 无需调用,立即执行,其实本质已经调用了
  • 多个立即执行函数之间用分号隔开

0 人点赞