JavaScript函数表达式与函数声明的差异及注意事项
作者:admin 时间:2022-6-9 17:46:9 浏览:函数声明和函数表达式是使用function关键字创建函数的两种方法,在本文中,我将介绍这两种方法的差异,以及使用它们时的注意事项。
函数表达式与函数声明
让我们举一个例子来说明差异——我们创建一个对数字求和的函数的 2 个版本:
function sumA(a, b) {
return a + b;
}
(function sumB(a, b) {
return a + b;
});
sumA(1, 2); // ???
sumB(1, 2); // ???
一种情况,你可以像往常一样定义函数(sumA函数)。另一种情况,函数被放置在一对括号中(sumB函数)。
如果你调用sumA(1, 2)
和sumB(1, 2)
会发生什么?
正如预期的那样,sumA(1, 2)
只需返回1和2数字的总和: 3。而,调用sumB(1, 2)
会引发错误Uncaught ReferenceError: sumB is not defined
。
解释是sumA
使用函数声明创建的,它在当前范围内创建一个函数变量(与函数名称相同)。但是sumB
是使用函数表达式创建的(它被包裹在括号中),它不会在当前范围内创建函数变量。
如果要访问使用函数表达式创建的函数,可以将函数对象保存到变量中:
const sum = (function sumB(a, b) {
return a + b;
});
sum(1, 2); // => 3
如何区分函数声明和函数表达式
下面是关于如何区分函数声明和函数表达式的简单方法:
如果语句以function关键字开头,则为函数声明,否则为函数表达式。
// 函数声明: 用 `function` 关键词开始
function sumA(a, b) {
return a + b;
}
// 函数表达式: 不以 `function` 关键词开始
const mySum = (function sumB(a, b) {
return a + b;
});
// 函数表达式: 不以 `function` 关键词开始
[1, 2, 3].reduce(function sum3(acc, number) {
return acc + number
});
从更高的角度来看,函数声明对于创建独立函数很有用,但函数表达式作为回调很好。
现在,让我们更深入地研究函数声明和函数表达式的使用。
2、函数声明
在前面的示例中已经看到的,sumA
是一个函数声明:
function sumA(a, b) {
return a + b;
}
sumA(4, 5); // => 9
当语句包含关键字后跟函数名、一对带参数的括号以及用一对花括号括起来的函数体时,就是函数声明。
function(param1, param2, paramN){ }
函数声明创建了一个函数变量——一个与函数名同名的变量(例如前面例子的sumA
)。函数变量可以在当前范围内(函数声明之前和之后)访问,甚至可以在函数的范围内访问。
函数变量通常用于调用函数或将函数对象传递给其他函数(传递给高阶函数)。
例如,我们编写一个函数sumArray(array)
,对数组的项进行递归求和(该数组可以包含数字或其他数组):
sumArray([10, [1, [5]]]); // => 16
function sumArray(array) {
let sum = 0;
for (const item of array) {
sum += Array.isArray(item) ? sumArray(item) : item;
}
return sum;
}
sumArray([1, [4, 6]]); // => 11
function sumArray(array) { ... }
是一个函数声明。
包含函数对象的函数变量sumArray
在当前范围内可用:在函数声明之前sumArray([10, [1, [5]]])
和之后sumArray([1, [4, 6]])
,以及在函数本身的范围内sumArray(item)
(允许递归调用)。
由于提升,函数变量在函数声明之前可用。
函数声明的注意事项
函数声明语法的作用是创建独立函数。函数声明应在全局范围内或直接在其他函数的范围内:
// 好!
function myFunc1(param1, param2) {
return param1 + param2;
}
function bigFunction(param) {
// 好!
function myFunc2(param1, param2) {
return param1 + param2;
}
const result = myFunc2(1, 3);
return result + param;
}
出于同样的原因,不建议在条件 (if
) 和循环 ( while
, for
)中使用函数声明:
// 不好!
if (myCondition) {
function myFunction(a, b) {
return a * b;
}
} else {
function myFunction(a, b) {
return a + b;
}
}
myFunction(2, 3);
使用函数表达式更好地执行有条件地创建函数。
3、函数表达式
当
function
关键字在表达式内创建函数(有或没有名称)时,就是函数表达式。
以下是使用表达式创建的函数的示例:
const sum = (function sumB(a, b) {
return a + b;
});
const myObject = {
myMethod: function() {
return 42;
}
};
const numbers = [4, 1, 6];
numbers.forEach(function callback(number) {
console.log(number);
// logs 4
// logs 1
// logs 1
});
在函数表达式中创建了两种函数:
- 如果表达式中的函数没有名称,例如
function() { return 42 }
,那么这是一个匿名函数表达式。 - 如果函数有名字,例如在前面的例子中的
sumB
和callback
,那么这是一个命名函数表达式。
函数表达式的注意事项
函数表达式非常适合作为条件创建的回调或函数:
// 有条件地创建函数
let callback;
if (true) {
callback = function() { return 42 };
} else {
callback = function() { return 3.14 };
}
// 作为回调使用函数
[1, 2, 3].map(function increment(number) {
return number + 1;
}); // => [2, 3, 4]
如果你创建了命名函数表达式,请注意函数变量仅在创建的函数范围内可用:
const numbers = [4];
numbers.forEach(function callback(number) {
console.log(callback); // logs function() { ... }
});
console.log(callback); // ReferenceError: callback is not defined
callback
是一个命名函数表达式,因此callback
函数变量仅在callback()
函数范围内可用,而在外部不可用。
但是,如果将函数对象存储到常规变量中,则可以在函数范围内外从该变量访问函数对象:
const callback = function(number) {
console.log(callback); // logs function() { ... }
};
const numbers = [4];
numbers.forEach(callback);
console.log(callback); // logs function() { ... }
4、总结
根据你使用function
关键字创建函数的方式,你可以通过两种方式创建函数:函数声明和函数表达式。
当你使用function
关键字开始语句时是函数声明,函数声明对于创建独立的通用函数很有用。
如果语句不以function
关键字开头,那么这是一个函数表达式,使用函数表达式创建的函数对于按条件创建回调或函数很有用。
相关文章
- 站长推荐