函数定义
现代 JavaScript Function 定义
Section titled “现代 JavaScript Function 定义”JavaScript functions(函数)是基本构建块。它们主要使用 function 关键字或较新的 arrow function(箭头函数)语法来定义。
你可以使用 function declarations(函数声明)、function expressions(函数表达式)和 arrow functions(箭头函数)来定义函数。
Function Declarations(函数声明)
Section titled “Function Declarations(函数声明)”Function declaration 定义一个命名的函数。其语法是:
function functionName(parameter1, parameter2) { // 要执行的代码 return result; // 可选 }
声明的函数不会立即执行。它们会被“hoisted”(提升)(参见下文),并在其 scope(作用域)范围内都可用,准备好稍后被调用(或“调用”,invoked)。
// 声明一个函数function multiply(a, b) { return a * b;}
// 调用函数const product = multiply(5, 10); // product 是 50关于分号的注意:Function declaration 是一种语句,但与大多数语句不同,它们通常不以分号结尾。然而,JavaScript 的自动分号插入 (Automatic Semicolon Insertion,ASI) 通常可以很好地处理这个问题。 |
|---|
Function Expressions(函数表达式)
Section titled “Function Expressions(函数表达式)”JavaScript function 也可以使用 expression(表达式)来定义。Function expression 可以存储在一个变量中。
最佳实践是使用 const 来定义 function expressions,以防止意外的重新赋值。
// 将一个函数表达式存储在变量中const calculateSum = function(a, b) { return a + b;}; // 这里需要分号,因为它是一个赋值语句的一部分。
// 使用变量调用函数const sum = calculateSum(4, 3); // sum 是 7上述示例中的函数是一个匿名函数(anonymous function,没有名称的函数),它被赋值给 calculateSum 变量。存储在变量中的函数使用变量名来调用。
Arrow Functions(箭头函数)(ES6+)
Section titled “Arrow Functions(箭头函数)(ES6+)”Arrow functions 是在 ES6 中引入的,提供了一种更简洁的语法来编写 function expressions。它们总是匿名的。
// 带有多个参数和块体(block body)的箭头函数const greet = (name) => { return `Hello, ${name}!`;};
// 只有一个参数的箭头函数(括号可选)const square = x => x * x;
// 没有参数的箭头函数const getRandom = () => Math.random();
console.log(greet('World')); // 输出: Hello, World!console.log(square(5)); // 输出: 25Arrow functions 的主要特点:
- 语法简洁,特别适用于简单的函数。
- 它们没有自己的
this绑定。this的值继承自外层词法作用域 (lexical scope)。这通常是期望的行为,尤其是在callbacks(回调函数)中。 - 它们不能用作构造函数(即不能与
new关键字一起使用)。 - 它们没有
arguments对象。应改用rest parameters(剩余参数)(...args)。
关于 this 在 arrow functions 中的更多细节,请查阅关于 JavaScript scope(作用域)和上下文(context)的资源。
The Function Constructor(构造函数)
Section titled “The Function Constructor(构造函数)”JavaScript functions 在技术上可以使用内置的 Function constructor(构造函数)来定义。然而,通常不建议使用这种方法。
// 示例(不推荐)const multiplyConstructor = new Function("a", "b", "return a * b");const result = multiplyConstructor(4, 3); // result 是 12避免使用 new Function() 的原因:
- 安全风险:它会评估字符串中的代码,类似于
eval()。 - 性能问题:这样创建的函数 JavaScript 引擎更难优化。
- 可读性:代码不够清晰,更难调试。
坚持使用 function declarations、function expressions 或 arrow functions。
Function Hoisting(函数提升)
Section titled “Function Hoisting(函数提升)”Hoisting 是 JavaScript 的一种行为,它会将声明(在概念上)移动到其 scope 的顶部,然后再执行代码。
Function Declarations:会被完全 hoisted。这意味着你可以在 function declaration 出现在代码之前调用它。
sayHello(); // 可以正常工作,因为 greet 被提升了
function sayHello() { console.log(“Hello!”); }
Function Expressions 和 Arrow Functions:不会以同样的方式被 hoisted。如果使用 var 定义,变量声明 (var x;) 会被 hoisted,但赋值 (x = function() {...};) 不会。如果使用 let 或 const 定义,变量会被 hoisted 但停留在“暂时性死区”(temporal dead zone)中,直到遇到声明行,因此你不能在此之前访问它。
// tryToCall(); // 这会导致错误(ReferenceError 或 TypeError,取决于使用的是 var/let/const)
const tryToCall = function() { console.log("Called!");};// 或者使用箭头函数:// const tryToCallArrow = () => console.log("Arrow called!");理解 hoisting 对于避免意外错误至关重要。使用 let 和 const 通常会导致更可预测的行为。
Immediately Invoked Function Expressions (IIFE)(立即调用函数表达式)
Section titled “Immediately Invoked Function Expressions (IIFE)(立即调用函数表达式)”Function expression 可以在定义后立即执行。这种模式被称为 IIFE(立即调用函数表达式),以前常被称为自调用函数(self-invoking function)。
IIFE 会自动被调用,因为 expression 后面紧跟着 ()。为了明确它是一个 expression,函数被包裹在括号中。
(function() { const message = "Hello from IIFE!"; console.log(message); // 这将立即执行})();
// 使用箭头函数的 IIFE(() => { const secret = "This is private to the IIFE."; console.log(secret);})();IIFE 对于创建局部 scope(作用域)、避免污染全局命名空间(global namespace)以及用于一次性设置代码非常有用。
Functions 可以用作值
Section titled “Functions 可以用作值”在 JavaScript 中,functions 是“一等公民”(first-class citizens)。这意味着它们可以像任何其他值一样对待:可以赋值给变量,作为 arguments(参数)传递给其他 functions,以及从 functions 返回。
function add(a, b) { return a * b;}
const operation = add; // 将函数赋给一个变量const result1 = operation(4, 3); // result1 是 12
const result2 = add(4, 3) * 2; // 在表达式中使用函数返回值// result2 是 24这种灵活性是 JavaScript 功能的核心部分,它支持 callbacks(回调函数)和 higher-order functions(高阶函数)等模式。
Functions 是 Objects
Section titled “Functions 是 Objects”虽然 typeof operator 对 functions 返回 "function",但它们在本质上是 JavaScript 中一种特殊类型的 object(对象)。
像 objects 一样,functions 可以有 properties(属性)和 methods(方法)。
arguments.length property(属性)(在非 arrow functions 中可用)返回函数被调用时实际传递的 arguments(参数)数量:
function countArgs(a, b) { console.log(arguments.length); // 传递的参数数量 // 现代方法:使用剩余参数 // function countArgsModern(...args) { console.log(args.length); }}
countArgs(1, 2, 3); // 输出: 3注意:arguments object 是一个类数组 (array-like) object。对于现代 JavaScript,通常最好使用 rest parameters (...args),它提供一个真正的 array(数组)。
toString() method 返回 function 的源代码 (source code) 作为字符串:
function exampleMultiply(a, b) { return a * b;}
const funcAsString = exampleMultiply.toString();console.log(funcAsString);/* 输出可能为:"function exampleMultiply(a, b) { return a * b;}"*/关键术语:定义为 object property 的 function 称为 method(方法)。设计用于创建新 objects(使用 new)的 function 称为 constructor function(构造函数)(arrow functions 不能是构造函数)。 |
|---|