在 JavaScript 中创建函数有两种方法:电报duoteJG信用搭建盘运营函数表达式和函数声明。在本文中,我们SG138win将讨论何时使用IDC函数表达式与函数声明,并解释它们之间的区别。
函数声明已经使用了很长时间,但函数表达式已经逐渐占据主导地位。许多开发人员不确定何时使用其中一种,因此他们最终使用了错误的一种。
函数表达式和函数声明之间有一些关键区别。让我们仔细看看这些差异,以及何时在代码中使用函数表达式与函数声明。
function funcDeclaration() {
return 'A function declaration';
}
let funcExpression = function () {
return 'A function expression';
}
什么是函数声明?
函数声明是在您创建函数并为其命名时。在编写 function 关键字时声明函数的名称,然后是函数名称。例如:
let myFunction = function() {
// do something
};
如您所见,函数名称 ( myFunction) 是在创建函数时声明的。这意味着您可以在定义之前调用该函数。
下面是一个函数声明的例子:
function add (a, b) {
return a + b;
};
什么是函数表达式?
函数表达式是在您创建函数并将其分配给变量时。该函数是匿名的,这意味着它没有名称。例如:
let myFunction = function() {
// do something
};
如您所见,该函数已分配给myFunction变量。这意味着您必须先定义该函数,然后才能调用它。
下面是一个函数表达式的例子:
let add = function (a, b) {
return a + b;
};
函数表达式和声明之间的区别
函数表达式和函数声明之间有几个关键区别:
函数声明被提升,而函数表达式则没有。这意味着您可以在定义函数声明之前调用它,但不能使用函数表达式执行此操作。
使用函数表达式,您可以在定义函数后立即使用它。使用函数声明,您必须等到整个脚本被解析。
函数表达式可以用作另一个函数的参数,但函数声明不能??。
函数表达式可以是匿名的,而函数声明则不能。
了解函数表达式中的作用域:JavaScript 提升差异
与let语句类似,函数声明被提升到其他代码的顶部。
函数表达式没有被提升。这允许他们从定义它们的范围内保留局部变量的副本。
通常,您可以互换使用函数声明和函数表达式。但有时函数表达式会生成更易于理解的代码,而不需要临时函数名。
如何在表达式和声明之间进行选择
那么,什么时候应该使用函数表达式与函数声明呢?
答案取决于您的需求。如果您需要更灵活的函数或未提升的函数,那么函数表达式是可行的方法。如果您需要更易读易懂的函数,请使用函数声明。
如您所见,这两种语法是相似的。最明显的区别是函数表达式是匿名的,而函数声明是有名字的。
今天,当你需要做一些函数表达式不能做的事情时,你通常会使用函数声明。如果您不需要做任何只能通过函数声明才能完成的事情,那么通常最好使用函数表达式。
当您需要创建递归函数或需要在定义函数之前调用该函数时,请使用函数声明。根据经验,当您不需要做任何这些事情时,使用函数表达式来获得更简洁的代码。
函数声明的好处
使用函数声明有几个关键的好处。
它可以使您的代码更具可读性。如果你有一个很长的函数,给它一个名字可以帮助你跟踪它在做什么。
函数声明是提升的,这意味着它们在您的代码中定义之前就可用。如果您需要在定义之前使用该函数,这将很有帮助。
函数表达式的好处
函数表达式也有一些好处。
它们比函数声明更灵活。您可以创建函数表达式并将它们分配给不同的变量,这在您需要在不同的地方使用相同的函数时会很有帮助。
函数表达式未提升,因此在代码中定义它们之前您不能使用它们。如果您想确保函数仅在定义后使用,这将很有帮助。
何时选择函数声明与函数表达式
在大多数情况下,很容易找出最适合您需要的函数定义方法。这些指南将帮助您在大多数情况下快速做出决定。
在以下情况下使用函数声明:
您需要一个更具可读性和可理解性的函数(例如一个长函数,或者您需要在不同地方使用的函数)
匿名函数不适合您的需求
您需要创建一个递归函数
您需要在定义之前调用该函数
在以下情况下使用函数表达式:
你需要一个更灵活的功能
你需要一个没有提升的功能
该函数只应在定义时使用
该函数是匿名的,或者不需要名称供以后使用
您想使用立即调用函数表达式 (IIFE) 等技术来控制函数何时执行
您想将函数作为参数传递给另一个函数
也就是说,在许多情况下,函数表达式的灵活性成为一项强大的资产。
解锁函数表达式:JavaScript 提升差异
有几种不同的方式可以使函数表达式变得比函数声明更有用。
闭包
其他函数的参数
立即调用函数表达式 (IIFE)
使用函数表达式创建闭包
当您想在函数执行之前为函数提供参数时,使用闭包。循环通过NodeList.
闭包允许您保留其他信息,例如索引,在函数执行后该信息不可用的情况下。
function tabsHandler(index) {
return function tabClickEvent(evt) {
// Do stuff with tab.
// The index variable can be accessed from within here.
};
}
let tabs = document.querySelectorAll('.tab'),
i;
for (i = 0; i < tabs.length; i += 1) {
tabs[i].onclick = tabsHandler(i);
}
附加的事件处理程序稍后执行(循环完成后),因此需要一个闭包来保留for循环的适当值。
// Bad code, demonstrating why a closure is needed
let i;
for (i = 0; i < list.length; i += 1) {
document.querySelector('#item' + i).onclick = function doSomething(evt) {
// Do something with item i
// But, by the time this function executes, the value of i is always list.length
}
}
doSomething()通过从for循环中提取函数,更容易理解为什么会出现问题。
// Bad code, demonstrating why a closure is needed
let list = document.querySelectorAll('.item'),
i,
doSomething = function (evt) {
// Do something with item i.
// But, by the time this function executes, the value of i is not what it was in the loop.
};
for (i = 0; i < list.length; i += 1) {
item[i].onclick = doSomething;
}
这里的解决方案是将索引作为函数参数传递给外部函数,以便它可以将该值传递给内部函数。您通常会看到处理函数用于组织内部返回函数所需的信息。
// The following is good code, demonstrating the use of a closure
let list = ['item1', 'item2', 'item3'],
i,
doSomethingHandler = function (itemIndex) {
return function doSomething(evt) {
// now this doSomething function can retain knowledge of
// the index variable via the itemIndex parameter,
// along with other variables that may be available too.
console.log('Doing something with ' + list[itemIndex]);
};
};
for (i = 0; i < list.length; i += 1) {
list[i].onclick = doSomethingHandler(i);
}
了解更多关于闭包及其用法的信息。
将函数表达式作为参数传递
函数表达式可以直接传递给函数,而不必分配给中间临时变量。
您最常以匿名函数的形式看到它们。这是一个熟悉的 jQuery 函数表达式示例:
$(document).ready(function () {
console.log('An anonymous function');
});
在使用诸如forEach().
它们也不必是未命名的匿名函数。命名函数表达式以帮助表达函数应该做什么并帮助调试是一个好主意:
let productIds = ['12356', '13771', '15492'];
productIds.forEach(function showProduct(productId) {
...
});
立即调用函数表达式 (IIFE)
IIFE 有助于防止您的函数和变量影响全局范围。
其中的所有属性都在匿名函数的范围内。这是一种常见的设计模式,用于防止您的代码在其他地方产生不希望的或不希望的副作用。
它还用作模块模式,在易于维护的部分中包含代码块。我们将在Demystifying JavaScript 闭包、回调和 IIFE中深入了解这些内容。
下面是一个 IIFE 的简单示例:
(function () {
// code in here
}());
…当用作模块时,可以为您的代码带来一些易于实现的可维护性。
let myModule = (function () {
let privateMethod = function () {
console.log('A private method');
},
someMethod = function () {
console.log('A public method');
},
anotherMethod = function () {
console.log('Another public method');
};
return {
someMethod: someMethod,
anotherMethod: anotherMethod
};
}());