
前言
大家好,我是逗号。祝大家周末愉快。
这段时间我们团队内部组织重学 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 函数表达式
在 JavaScript 中,「函数是第一等对象」,因为它不仅仅可以像对象一样拥有属性和方法,而且同普通对象不一样的是它还可以被调用执行。函数表达式能更直观地看出是创建了一个对象。
函数声明在 JavaScript 解析时,进行「函数提升」,因此在同一个作用域内,函数声明会被提升到作用域的最前面,该函数都可以进行调用。而函数表达式的值在 JavaScript 「运行时」,就已经被确定,并且在表达式赋值完成后,该函数才能调用。
函数表达式的使用范围更广。JavaScript 规范只是允许它们作为顶级语句。它们可以出现在全局代码中,或者嵌入在其他函数中,但它们不能出现在「循环、条件判断、或者
try/catch/finally/switch」 语句中。函数声明不能放在
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 局部变量
「局部变量」指只能在当前变量声明的函数内部调用;「全局变量」是指在整个代码中都可以调用的变量。
变量声明需要使用
var关键字声明,但是在 JavaScript 中可以不带var「隐式」的声明一个变量,这种变量会自动被识别为「全局变量」。
三、函数的构成
3.1 参数
我们可以使用参数(也称为 「“函数参数”」 )来将任意数据传递给函数。
在下面的例子中,函数接受两个参数:name 和 text。
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的函数声明和函数表达式