《JavaScript 温故知新 - 函数》

561 阅读7分钟

前言

大家好,我是逗号。祝大家周末愉快。

这段时间我们团队内部组织重学 JavaScript 的学习小组,旨在帮助我们查缺补漏,巩固自己的基础。

如果我有哪里写的不对不好的地方,欢迎大家指出。

接下来让我们一起来复习一下 JavaScript 的一等公民吧!

我们来先看看今天文章内容的大纲内容:

函数是 JavaScript 中的基本组件之一。 一个函数是 JavaScript 过程, 一组执行任务或计算值的语句。要使用一个函数,你必须将其定义在你希望调用它的作用域内。

一、函数定义

JavaScript 使用关键字 function 定义函数。函数可以通过声明定义,也可以是一个表达式。

函数的组成部分依次为:

  • 函数的名称。
  • 函数的参数列表。
  • 定义函数的 JavaScript 语句,用大括号 {} 包裹的语句。

1.1 函数声明

function fn(params) {
 // dosomething
}

函数在声明后不会立即执行,在我们需要的时候通过 函数名(参数1, 参数2...) 的方式调用。

function calcSum(x, y) {
 return x + y;
}

// 执行函数体
calcSum(1, 6); // 7

1.2 函数表达式

JavaScript 函数可以通过一个表达式定义。
函数表达式可以存储在变量中,我们来看看下面这个例子:

var calcSum = function (x, y) { return x + y };

在函数表达式存储在变量后,变量也可以作为一个函数调用:

var calcSum = function (x, y) { return x + y };
var sum = calcSum(1, 6); // 7

上面这个例子实际上是一个匿名函数(函数没有名称)。
函数存储在变量中,不需要函数名称,通常通过变量名来调用。

1.3 Function() 构造函数

在上面的例子中,我们是通过使用 function 关键字来创建函数的。 函数同样可以通过使用内置的 JavaScript 函数构造器( Function() )来定义。

var calcSum = new Function('x', 'y', 'return x + y');

var sum = calcSum(4, 3); // 7

1.4 函数声明 VS 函数表达式

  1. 在 JavaScript 中,函数是第一等对象,因为它不仅仅可以像对象一样拥有属性和方法,而且同普通对象不一样的是它还可以被调用执行。函数表达式能更直观地看出是创建了一个对象。

  2. 函数声明在 JavaScript 解析时,进行函数提升,因此在同一个作用域内,函数声明会被提升到作用域的最前面,该函数都可以进行调用。而函数表达式的值在 JavaScript 运行时,就已经被确定,并且在表达式赋值完成后,该函数才能调用。

  3. 函数表达式的使用范围更广。JavaScript 规范只是允许它们作为顶级语句。它们可以出现在全局代码中,或者嵌入在其他函数中,但它们不能出现在循环、条件判断、或者 try/catch/finally/switch 语句中。

  4. 函数声明不能放在 if 语句中,在一些浏览器中无论条件为 false 还是 true ,函数都会被定义。

我们来看看当我们通过函数表达式和函数声明定义一个同名的函数会出现什么问题:

var showMsg; // undefined 变量提升
showMsg(); // 逗号 函数声明被提升
var showMsg = function() {
 console.log('douhao')
} // 函数表达式在这里开始覆盖函数声明的定义
showMsg(); // douhao
function showMsg() {
 console.log('逗号')
}
showMsg(); // douhao 这里执行的结果是函数表达式的值

在我们日常协作开发中,如果两个人定义了同名的函数,就可能掉入这样的 “致命”陷阱。出现这个陷阱的本质原因体现在两种类型在函数提升和运行时机(解析时/运行时)上的差异。

二、变量

1.1 局部变量

如果在函数体中声明一个变量,那只会在该函数内部可见,外部是无法访问到这个变量的。

function showMsg() {
 let message = "Hello, I'm 逗号"
  
  console.log(message)
}

showMsg(); // Hello, I'm 逗号

console.log(message); // Uncaught ReferenceError: message is not defined

1.2 全局变量

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

let name = "逗号";

function showName() {
 name = "douhao"
  console.log('Hello ' + name);
}

console.log(name); // 逗号 在函数调用之前

showName(); // Hello douhao

console.log(name); // douhao 在函数调用之后,值被修改了

只有在没有局部变量的情况下才会使用全局变量。 如果函数内部声明了同名的变量,那么函数会 遮蔽 全局变量。 例如下面的例子中,函数使用局部变量的 name ,而全局变量被忽略:

let name = '逗号';

function showName() {
 let name = 'douhao';
  console.log('Hello ' + name);
}

showName(); // Hello douhao

console.log(name); // 逗号 因为函数在内部声明了同名变量,没有访问修改到全局变量

1.3 全局变量 VS 局部变量

  1. 局部变量指只能在当前变量声明的函数内部调用;全局变量是指在整个代码中都可以调用的变量。

  2. 变量声明需要使用 var 关键字声明,但是在 JavaScript 中可以不带 var 隐式的声明一个变量,这种变量会自动被识别为全局变量

三、函数的构成

3.1 参数

我们可以使用参数(也称为 “函数参数” )来将任意数据传递给函数。 在下面的例子中,函数接受两个参数:nametext

function showMsg(name, text) {
 console.log(name + ': ' + text)
}

showMsg('逗号', 'Hello'); // 逗号: Hello

并不是函数定义的值我们都必须传入,如果未提供参数的话,那么其默认值则是 undefined

3.2 默认值

如果我们不想传递 text ,那么我们可以在声明函数的时候给它设定一个默认值:

function showMsg(name, text = 'Hello') {
 console.log(name + ': ' + text)
}

showMsg('逗号'); // 逗号: Hello

在这里 'Hello' 是一个字符串,但它可以是更复杂的表达式,并且只会在缺少参数时才会被计算和分配。

3.3 返回值

函数可以将一个值返回到调用代码中作为结果。
最简单的例子是将两个值相加的结果返回:

function sum(x, y) {
 return x + y;
}

let result = sum(4,3);
console.log(result); // 7

指令 return 可以在函数的任意位置。当执行到达时,函数停止执行,并将值返回给调用代码。
只使用 return 但没有返回值也是可行的。但这会导致函数立即退出。
空值的 return 或没有 return 的函数返回值为 undefined

function doNothing() {}

console.log(doNothing() === undefined); // true

// ----------------------------------------------------------

function doNothing() { return };

console.log(doNothing() === undefined); // true

3.4 函数的命名

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

  • show :开头的函数通常会显示某些内容;
  • get :返回一个值;
  • calc :计算某些内容;
  • create :创建某些内容;
  • check :检查某些内容并返回。
  • ......

四、总结

  • 定义函数的三种方式:使用关键字 function 方式、使用匿名函数方式、使用构造函数 Function 方式。

  • 作为参数传递给函数的值,会被复制到函数的局部变量

  • 函数可以访问全局变量。但它只能从内到外起作用。函数外部的代码不能访问到函数内部的局部变量

  • 函数可以有返回值。也可以没有返回值,则返回的结果为 undefined

  • 函数名应该清楚的描述函数的功能

参考文章

现代JavaScript教程 - 函数
函数 - JavaScript | MDN
函数声明VS函数表达式
关于Javascript的函数声明和函数表达式