函数是可复用的代码块。JavaScript 中函数是一等公民:可以被赋值、作为参数传递、作为返回值返回。
function add(a, b) { return a + b;}
console.log(add(2, 3)); // 5特点:会被“函数提升”(可在声明之前调用)。
const multiply = function (a, b) { return a * b;};
console.log(multiply(2, 3)); // 6特点:不会被提升到可用状态,需先定义后使用。可命名/匿名,用于回调更灵活。
const divide = (a, b) => a / b;
// 多语句需显式 returnconst sum = (arr) => { let s = 0; for (const n of arr) s += n; return s;};特点:
this/arguments/super/new.target,this 由词法作用域决定new)function greet(name = "World") { return `Hello, ${name}!`;}function sumAll(...nums) { return nums.reduce((a, b) => a + b, 0);}
sumAll(1, 2, 3); // 6const arr = [1, 2, 3];console.log(sumAll(...arr)); // 6function parse(json, fallback = null) { try { return JSON.parse(json); } catch { return fallback; }}const obj = { x: 42, normal() { return function () { return this.x; }; }, arrow() { return () => this.x; },};
const f1 = obj.normal();console.log(f1()); // undefined(非严格模式下可能是全局)console.log(f1.call(obj)); // 42(显式绑定)
const f2 = obj.arrow();console.log(f2()); // 42(箭头函数捕获词法 this)结论:需要稳定的 this 指向时,优先使用箭头函数作为回调;作为对象方法且需要动态 this 时用常规方法写法。
闭包是指函数可以“记住并访问”其词法作用域中的变量,即使函数在其定义作用域之外执行。
function makeCounter() { let count = 0; // 私有变量 return function () { count += 1; return count; };}
const counter = makeCounter();console.log(counter()); // 1console.log(counter()); // 2常见用途:私有状态、函数工厂、缓存。
// 回调风格function fetchDataCb(url, cb) { setTimeout(() => cb(null, { url, ok: true }), 100);}
// Promise 风格function fetchData(url) { return new Promise((resolve) => { setTimeout(() => resolve({ url, ok: true }), 100); });}
// async/awaitasync function load() { const data = await fetchData("/api"); return data.ok;}建议:新代码优先使用 Promise 与 async/await,避免回调地狱。
function once(fn) { let called = false; let result; return function (...args) { if (!called) { called = true; result = fn.apply(this, args); } return result; };}
const init = once(() => console.log("init"));init();init(); // 第二次不执行const add3 = (a) => (b) => (c) => a + b + c;console.log(add3(1)(2)(3)); // 6const compose = (...fns) => (x) => fns.reduceRight((v, f) => f(v), x);const pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);JS 无原生重载,常用模式:
function format(input) { if (typeof input === "number") return input.toFixed(2); if (Array.isArray(input)) return input.join(","); if (input && typeof input === "object") return JSON.stringify(input); return String(input);}function demo() { console.log(arguments.length); // 类数组,不是数组}
function better(...args) { console.log(args.length); // 真数组}const obj2 = { x: 1, getX() { return this.x; },};
const getX = obj2.getX;console.log(getX()); // undefined(严格模式)console.log(getX.call(obj2)); // 1函数是 JS 抽象的核心。掌握多种定义方式、this 绑定、闭包与异步控制流,可以写出可读、可维护且高性能的代码。