本文目录导读:

- 基本函数声明与表达式
- 回调函数(Callback)
- 高阶函数(返回函数/接收函数)
- IIFE(立即执行函数表达式)
- 构造函数与原型
- 函数柯里化(Currying)
- 防抖与节流(性能优化案例)
- 动态创建函数(
new Function) - 递归函数
- 使用
call、apply、bind改变 this 指向
在 JavaScript 中,函数(Function) 是一等公民,既可以作为普通函数调用,也可以作为构造函数、对象方法、回调函数等使用。
下面通过几个经典案例,展示 Function 的多种用法和特性。
基本函数声明与表达式
// 函数声明(提升)
function add(a, b) {
return a + b;
}
// 函数表达式(不提升)
const multiply = function(a, b) {
return a * b;
};
// 箭头函数(没有自己的 this)
const subtract = (a, b) => a - b;
console.log(add(5, 3)); // 8
console.log(multiply(5, 3)); // 15
console.log(subtract(5, 3)); // 2
回调函数(Callback)
回调是 JavaScript 中应用最广泛的函数用法,常用于异步或事件处理。
function processData(data, callback) {
console.log("处理数据...");
const result = data.map(item => item * 2);
callback(result);
}
processData([1, 2, 3], (result) => {
console.log("回调结果:", result); // [2, 4, 6]
});
// 定时器回调
setTimeout(() => {
console.log("3秒后执行");
}, 3000);
高阶函数(返回函数/接收函数)
// 返回一个新函数(闭包)
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
// 接收函数作为参数
function repeat(times, fn) {
for (let i = 0; i < times; i++) {
fn(i);
}
}
repeat(3, (i) => console.log(`第${i}次`));
IIFE(立即执行函数表达式)
用于创建独立作用域,避免全局污染。
(function() {
const secret = "这是一个私有变量";
console.log("IIFE执行了", secret);
})();
// 模块模式(返回对象暴露公共 API)
const myModule = (function() {
let privateVar = 0;
function privateMethod() {
return "私有方法";
}
return {
publicMethod: function() {
privateVar++;
return privateMethod() + " - 次数: " + privateVar;
}
};
})();
console.log(myModule.publicMethod()); // 私有方法 - 次数: 1
构造函数与原型
使用 new 关键字创建对象。
function Person(name, age) {
this.name = name;
this.age = age;
}
// 在原型上添加方法
Person.prototype.sayHello = function() {
console.log(`你好,我是 ${this.name},今年 ${this.age} 岁`);
};
const person = new Person("张三", 25);
person.sayHello(); // 你好,我是 张三,今年 25 岁
// 检查原型
console.log(person instanceof Person); // true
函数柯里化(Currying)
将多参数函数转换为链式调用单参数函数。
// 普通函数
function curryAdd(a, b, c) {
return a + b + c;
}
// 柯里化函数
function curriedAdd(a) {
return function(b) {
return function(c) {
return a + b + c;
};
};
}
console.log(curriedAdd(1)(2)(3)); // 6
// 手动柯里化函数生成器
function curry(fn, ...args) {
return fn.length <= args.length
? fn(...args)
: (...more) => curry(fn, ...args, ...more);
}
const sum = (a, b, c) => a + b + c;
const curriedSum = curry(sum);
console.log(curriedSum(1)(2)(3)); // 6
防抖与节流(性能优化案例)
这是实际开发中最常见的函数进阶用法。
// 防抖:触发后等待 delay 毫秒再执行,如果再次触发则重新计时
function debounce(fn, delay = 500) {
let timer = null;
return function(...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
// 节流:保证在指定时间间隔内只执行一次
function throttle(fn, interval = 500) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime >= interval) {
lastTime = now;
fn.apply(this, args);
}
};
}
// 模拟使用
const search = (query) => console.log("搜索:", query);
const debouncedSearch = debounce(search, 300);
// 连续调用多次,只会在最后一次调用后 300ms 执行一次
debouncedSearch("a");
debouncedSearch("ab");
debouncedSearch("abc");
动态创建函数(new Function)
虽然不推荐,但在某些场景下需要从字符串创建函数。
// 创建一个动态函数,输入两个参数,返回它们的和一些逻辑
const dynamicFunction = new Function('a', 'b', 'return a + b');
console.log(dynamicFunction(2, 3)); // 5
// 更复杂一点的例子
const createMathFunction = (operator) => {
return new Function('a', 'b', `return a ${operator} b`);
};
const multiplyFunc = createMathFunction('*');
console.log(multiplyFunc(6, 7)); // 42
注意:
new Function中的代码不是在当前作用域执行的,而是在全局作用域执行,无法访问函数外部的局部变量。
递归函数
函数调用自身,常用于树形结构或数学计算。
// 计算阶乘
function factorial(n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
// 扁平化嵌套数组
function flatten(arr) {
return arr.reduce((result, item) => {
return result.concat(Array.isArray(item) ? flatten(item) : item);
}, []);
}
console.log(factorial(5)); // 120
console.log(flatten([1, [2, [3]], 4])); // [1, 2, 3, 4]
使用 call、apply、bind 改变 this 指向
const user1 = { name: "张三", age: 25 };
const user2 = { name: "李四", age: 30 };
function introduce(extra) {
console.log(`大家好,我是${this.name},今年${this.age}岁。${extra || ''}`);
}
// call:逐个传递参数
introduce.call(user1, "很高兴认识你!");
// apply:传递参数数组
introduce.apply(user2, ["请多关照!"]);
// bind:返回绑定好 this 的新函数
const introduceUser1 = introduce.bind(user1);
introduceUser1("你好!");
| 场景 | 核心技术 | 应用示例 |
|---|---|---|
| 异步处理 | 回调函数 | 定时器、网络请求 |
| 数据抽象 | 闭包/IIFE | 模块化、计数器 |
| 代码复用 | 高阶函数 | 防抖、节流、柯里化 |
| 面向对象 | 构造函数+原型 | 创建类对象 |
| 函数式编程 | 链式调用 | 柯里化、组合函数 |
| 权限控制 | call/apply/bind | 改变 this 指向 |
这些案例覆盖了 JavaScript 函数的常用场景,理解它们会帮助你写出更优雅、更模块化的代码。