函数(Function)
JavaScript 中的函数:声明、表达式、箭头函数的使用和底层原理
📖 入门:基础使用
1. 函数声明(Function Declaration)
基本语法:
function functionName(parameters) {
// 函数体
return value;
}示例:
function add(a, b) {
return a + b;
}
console.log(add(5, 3)); // 8特点:
- ✅ 函数提升(hoisting)
- ✅ 可以在声明前调用
- ✅ 属于函数作用域
2. 函数表达式(Function Expression)
基本语法:
const functionName = function(parameters) {
// 函数体
return value;
};示例:
const subtract = function(a, b) {
return a - b;
};
console.log(subtract(10, 3)); // 7特点:
- ❌ 不提升(必须先声明后使用)
- ✅ 可以作为值传递
- ✅ 可以匿名
3. 箭头函数(Arrow Function)
基本语法:
const functionName = (parameters) => {
// 函数体
return value;
};简写形式:
// 单个参数,可以省略括号
const square = x => x * x;
// 单个表达式,可以省略 return 和花括号
const double = x => x * 2;
// 多个参数
const add = (a, b) => a + b;
// 无参数
const greet = () => console.log("Hello");示例:
const multiply = (a, b) => a * b;
console.log(multiply(4, 5)); // 20
// 数组方法中使用
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(x => x * 2);
console.log(doubled); // [2, 4, 6, 8, 10]特点:
- ✅ 语法简洁
- ✅ 不绑定
this(词法this) - ❌ 不能作为构造函数
- ❌ 没有
arguments对象
4. 函数参数
4.1 默认参数(Default Parameters)
基本语法:
function greet(name = "Guest") {
console.log(`Hello, ${name}!`);
}示例:
function greet(name = "Guest", age = 0) {
console.log(`Hello, ${name}, you are ${age} years old.`);
}
greet("Alice", 25); // Hello, Alice, you are 25 years old.
greet("Alice"); // Hello, Alice, you are 0 years old.
greet(); // Hello, Guest, you are 0 years old.4.2 Rest 参数(Rest Parameters)
基本语法:
function functionName(...args) {
// args 是一个数组
}示例:
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
console.log(sum(1, 2)); // 34.3 参数解构(Destructuring)
基本语法:
function functionName({ prop1, prop2 }) {
// 使用 prop1, prop2
}示例:
function greet({ name, age }) {
console.log(`Hello, ${name}, you are ${age} years old.`);
}
greet({ name: "Alice", age: 25 }); // Hello, Alice, you are 25 years old.5. 立即执行函数(IIFE)
基本语法:
(function() {
// 代码块
})();示例:
(function() {
let message = "Hello";
console.log(message); // Hello
})();
// message 在这里不可访问用途:
- 创建私有作用域
- 避免变量污染全局
🚀 提高:底层原理
1. 函数执行上下文(Execution Context)
1.1 执行上下文的创建
函数调用时的执行过程:
1. 创建执行上下文(Execution Context)
2. 创建变量环境(Variable Environment)
3. 创建词法环境(Lexical Environment)
4. 绑定 this
5. 初始化参数
6. 执行函数体
7. 返回结果
示例分析:
function add(a, b) {
let sum = a + b;
return sum;
}
let result = add(5, 3);执行上下文结构:
FunctionExecutionContext {
VariableEnvironment: {
a: 5,
b: 3,
sum: 8
},
LexicalEnvironment: {
// 词法环境
},
ThisBinding: undefined (严格模式) 或 global (非严格模式)
}
1.2 变量提升和函数提升
函数声明的提升:
// 代码
console.log(foo); // [Function: foo]
foo(); // "Hello"
function foo() {
console.log("Hello");
}
// 实际执行顺序(提升后)
function foo() { // 函数提升
console.log("Hello");
}
console.log(foo); // [Function: foo]
foo(); // "Hello"函数表达式的提升:
// 代码
console.log(bar); // undefined
// bar(); // 报错:bar is not a function
var bar = function() {
console.log("Hello");
};
// 实际执行顺序(提升后)
var bar; // 变量提升
console.log(bar); // undefined
bar = function() { // 赋值留在原地
console.log("Hello");
};2. 作用域链(Scope Chain)
2.1 作用域链的形成
原理:
- 每个函数都有作用域链
- 作用域链指向外层作用域
- 形成链式查找机制
示例:
let globalVar = "global";
function outer() {
let outerVar = "outer";
function inner() {
let innerVar = "inner";
console.log(innerVar); // "inner"(当前作用域)
console.log(outerVar); // "outer"(外层作用域)
console.log(globalVar); // "global"(全局作用域)
}
inner();
}
outer();作用域链结构:
inner 函数的作用域链:
inner LexicalEnvironment -> outer LexicalEnvironment -> Global LexicalEnvironment
2.2 闭包(Closure)
闭包的定义:
- 函数可以访问其外部作用域的变量
- 即使外部函数已经执行完毕
示例:
function outer() {
let count = 0;
function inner() {
count++;
console.log(count);
}
return inner;
}
const counter = outer();
counter(); // 1
counter(); // 2
counter(); // 3闭包原理:
outer 函数执行完毕后:
- outer 的执行上下文被销毁
- 但 inner 函数引用了 outer 的变量 count
- count 被保留在内存中(闭包)
- inner 函数可以继续访问 count
3. this 绑定
3.1 this 的绑定规则
默认绑定:
function foo() {
console.log(this); // global (非严格模式) 或 undefined (严格模式)
}
foo();隐式绑定:
const obj = {
name: "Alice",
greet: function() {
console.log(this.name); // "Alice"
}
};
obj.greet();显式绑定:
function greet() {
console.log(this.name);
}
const obj = { name: "Alice" };
greet.call(obj); // "Alice"
greet.apply(obj); // "Alice"
const bound = greet.bind(obj);
bound(); // "Alice"new 绑定:
function Person(name) {
this.name = name;
}
const person = new Person("Alice");
console.log(person.name); // "Alice"3.2 箭头函数的 this
箭头函数的 this 规则:
- 箭头函数没有自己的
this this继承自外层作用域(词法this)
示例对比:
const obj = {
name: "Alice",
// 普通函数
greet1: function() {
setTimeout(function() {
console.log(this.name); // undefined(this 指向 global)
}, 100);
},
// 箭头函数
greet2: function() {
setTimeout(() => {
console.log(this.name); // "Alice"(this 继承外层)
}, 100);
}
};
obj.greet1(); // undefined
obj.greet2(); // "Alice"4. 函数作为一等公民(First-Class Citizen)
函数的特性:
- ✅ 可以作为值赋值给变量
- ✅ 可以作为参数传递
- ✅ 可以作为返回值
- ✅ 可以动态创建
示例:
// 作为值
const add = function(a, b) { return a + b; };
// 作为参数
function calculate(a, b, operation) {
return operation(a, b);
}
console.log(calculate(5, 3, add)); // 8
// 作为返回值
function createMultiplier(multiplier) {
return function(x) {
return x * multiplier;
};
}
const double = createMultiplier(2);
console.log(double(5)); // 105. 函数式编程基础
5.1 高阶函数(Higher-Order Function)
定义:接收函数作为参数或返回函数的函数
示例:
// map:数组映射
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(x => x * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// filter:数组过滤
const evens = numbers.filter(x => x % 2 === 0);
console.log(evens); // [2, 4]
// reduce:数组归约
const sum = numbers.reduce((a, b) => a + b, 0);
console.log(sum); // 155.2 纯函数(Pure Function)
定义:
- 相同输入总是产生相同输出
- 没有副作用(不修改外部状态)
示例:
// 纯函数
function add(a, b) {
return a + b;
}
// 非纯函数
let count = 0;
function increment() {
count++; // 副作用:修改外部状态
return count;
}📝 最佳实践
- 优先使用函数声明或箭头函数:避免
var+ 函数表达式 - 合理使用默认参数:提高函数易用性
- 理解
this绑定:避免this指向错误 - 利用闭包:创建私有变量和模块化
- 编写纯函数:提高代码可测试性和可维护性