1. JavaScript函数基础与核心概念
JavaScript函数是这门语言最基础也是最重要的组成部分之一。作为一门函数式编程语言,JavaScript中的函数不仅仅是执行特定任务的代码块,更是一等公民(First-class citizen),这意味着函数可以像其他数据类型一样被传递和使用。
1.1 函数定义方式
在JavaScript中,函数主要有三种定义方式:
- 函数声明(Function Declaration):
function square(number) { return number * number; }特点:存在函数提升(hoisting),可以在定义前调用。
- 函数表达式(Function Expression):
const square = function(number) { return number * number; };特点:不存在提升,必须在定义后使用。
- 箭头函数(Arrow Function,ES6新增):
const square = (number) => number * number;特点:简洁语法,不绑定自己的this、arguments、super或new.target。
提示:箭头函数在单参数时可省略括号,单行时可省略return和花括号,但多行时必须使用return。
1.2 函数参数处理
JavaScript函数的参数处理非常灵活:
- 默认参数(ES6):
function greet(name = 'Guest') { console.log(`Hello, ${name}!`); }- 剩余参数(Rest Parameters):
function sum(...numbers) { return numbers.reduce((acc, num) => acc + num, 0); }- arguments对象(传统方式):
function showArgs() { console.log(arguments); // 类数组对象 }注意:箭头函数没有自己的arguments对象,但可以访问外围函数的arguments。
2. 常用内置函数分类解析
2.1 数据类型转换函数
- parseInt():
parseInt('10'); // 10 parseInt('101', 2); // 5 (二进制转换)- parseFloat():
parseFloat('3.14'); // 3.14- Number():
Number('123'); // 123 Number(true); // 1- String():
String(123); // "123" String(null); // "null"- Boolean():
Boolean(''); // false Boolean(0); // false Boolean([]); // true2.2 数学计算函数
- Math对象常用方法:
Math.abs(-5); // 5 Math.ceil(4.2); // 5 Math.floor(4.9); // 4 Math.round(4.5); // 5 Math.max(1, 3, 2); // 3 Math.min(1, 3, 2); // 1 Math.random(); // 0~1之间的随机数 Math.pow(2, 3); // 8 (ES7可用2**3)- 指数和对数函数:
Math.exp(1); // e的1次方 ≈ 2.718 Math.log(Math.E); // 1 (自然对数) Math.log10(100); // 2 Math.log2(8); // 32.3 字符串处理函数
- 基本字符串方法:
'hello'.charAt(1); // 'e' 'hello'.concat(' world'); // 'hello world' 'hello'.includes('ell'); // true 'hello'.indexOf('l'); // 2 'hello'.lastIndexOf('l'); // 3 'hello'.slice(1, 3); // 'el' 'hello'.substring(1, 3); // 'el' 'hello'.substr(1, 3); // 'ell' (已废弃) 'hello'.repeat(2); // 'hellohello'- 大小写转换:
'Hello'.toLowerCase(); // 'hello' 'hello'.toUpperCase(); // 'HELLO'- trim系列:
' hello '.trim(); // 'hello' ' hello '.trimStart(); // 'hello ' ' hello '.trimEnd(); // ' hello'- ES6新增方法:
'hello'.startsWith('he'); // true 'hello'.endsWith('lo'); // true 'hello'.padStart(8, '*'); // '***hello' 'hello'.padEnd(8, '*'); // 'hello***'2.4 数组操作函数
- 基本数组方法:
const arr = [1, 2, 3]; arr.push(4); // [1,2,3,4] arr.pop(); // [1,2,3] arr.unshift(0); // [0,1,2,3] arr.shift(); // [1,2,3] arr.concat([4,5]); // [1,2,3,4,5] arr.join('-'); // '1-2-3' arr.reverse(); // [3,2,1] arr.slice(1,3); // [2,3] arr.splice(1,1,'a'); // [1,'a',3] (原数组变为[1,'a',3])- 搜索和位置方法:
[1,2,3].indexOf(2); // 1 [1,2,3].lastIndexOf(2); // 1 [1,2,3].includes(2); // true [1,2,3].find(x => x > 1); // 2 [1,2,3].findIndex(x => x > 1); // 1- 迭代方法:
[1,2,3].forEach(x => console.log(x)); [1,2,3].map(x => x * 2); // [2,4,6] [1,2,3].filter(x => x > 1); // [2,3] [1,2,3].reduce((acc, x) => acc + x, 0); // 6 [1,2,3].some(x => x > 2); // true [1,2,3].every(x => x > 0); // true- ES6+新增方法:
Array.from('hello'); // ['h','e','l','l','o'] Array.of(1,2,3); // [1,2,3] [1,2,3].fill(0); // [0,0,0] [1,2,3].copyWithin(0,1); // [2,3,3] [1,[2,3]].flat(); // [1,2,3] [1,2,3].flatMap(x => [x, x*2]); // [1,2,2,4,3,6]2.5 对象相关函数
- 对象属性操作:
const obj = {a:1, b:2}; Object.keys(obj); // ['a','b'] Object.values(obj); // [1,2] Object.entries(obj); // [['a',1],['b',2]] Object.assign({}, obj, {b:3}); // {a:1,b:3} Object.freeze(obj); // 冻结对象 Object.seal(obj); // 密封对象- 原型相关方法:
Object.create(proto); Object.getPrototypeOf(obj); Object.setPrototypeOf(obj, proto);- 属性描述符:
Object.getOwnPropertyDescriptor(obj, 'a'); Object.defineProperty(obj, 'c', {value:3}); Object.defineProperties(obj, {c:{value:3},d:{value:4}});2.6 日期时间函数
- Date构造函数:
new Date(); // 当前时间 new Date(2023, 0, 1); // 2023年1月1日 new Date('2023-01-01'); // ISO格式日期- 常用实例方法:
const now = new Date(); now.getFullYear(); // 年份 now.getMonth(); // 月份(0-11) now.getDate(); // 日期(1-31) now.getHours(); // 小时(0-23) now.getMinutes(); // 分钟(0-59) now.getSeconds(); // 秒数(0-59) now.getTime(); // 时间戳(毫秒) now.toISOString(); // ISO格式字符串 now.toLocaleString(); // 本地格式字符串- 日期计算:
const date = new Date(); date.setDate(date.getDate() + 7); // 一周后2.7 JSON处理函数
- JSON.stringify():
JSON.stringify({a:1, b:2}); // '{"a":1,"b":2}' JSON.stringify({a:1, b:2}, null, 2); // 带缩进的格式化输出- JSON.parse():
JSON.parse('{"a":1,"b":2}'); // {a:1, b:2}注意:JSON.stringify会忽略函数和undefined属性,Date对象会被转为ISO字符串。
3. 高阶函数与函数式编程
3.1 高阶函数概念
高阶函数是指可以接收函数作为参数,或者返回函数作为结果的函数。JavaScript中常见的高阶函数包括:
// 接收函数作为参数 function operate(a, b, operation) { return operation(a, b); } // 返回函数 function multiplier(factor) { return function(x) { return x * factor; }; }3.2 常见高阶函数模式
- 函数柯里化:
function curry(fn) { return function curried(...args) { if (args.length >= fn.length) { return fn.apply(this, args); } else { return function(...args2) { return curried.apply(this, args.concat(args2)); }; } }; } const add = (a, b, c) => a + b + c; const curriedAdd = curry(add); curriedAdd(1)(2)(3); // 6- 函数组合:
function compose(...fns) { return function(x) { return fns.reduceRight((acc, fn) => fn(acc), x); }; } const add1 = x => x + 1; const double = x => x * 2; const addThenDouble = compose(double, add1); addThenDouble(5); // 12- 记忆化函数:
function memoize(fn) { const cache = new Map(); return function(...args) { const key = JSON.stringify(args); if (cache.has(key)) return cache.get(key); const result = fn.apply(this, args); cache.set(key, result); return result; }; } const factorial = memoize(n => n <= 1 ? 1 : n * factorial(n - 1));3.3 函数式编程工具函数
- 节流(throttle)函数:
function throttle(fn, delay) { let lastCall = 0; return function(...args) { const now = Date.now(); if (now - lastCall >= delay) { lastCall = now; return fn.apply(this, args); } }; }- 防抖(debounce)函数:
function debounce(fn, delay) { let timer; return function(...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); }; }- 单次执行函数:
function once(fn) { let called = false; return function(...args) { if (!called) { called = true; return fn.apply(this, args); } }; }4. 异步编程相关函数
4.1 Promise相关函数
- Promise构造函数:
new Promise((resolve, reject) => { // 异步操作 if (success) resolve(value); else reject(error); });- Promise静态方法:
Promise.resolve(value); // 返回一个已解决的Promise Promise.reject(error); // 返回一个已拒绝的Promise Promise.all([p1, p2]); // 所有Promise都解决时解决 Promise.allSettled([p1, p2]); // 所有Promise都完成时解决 Promise.race([p1, p2]); // 第一个完成的Promise Promise.any([p1, p2]); // 第一个解决的Promise- Promise实例方法:
promise.then(onFulfilled, onRejected); promise.catch(onRejected); promise.finally(onFinally);4.2 async/await函数
- async函数声明:
async function fetchData() { const response = await fetch(url); const data = await response.json(); return data; }- async函数表达式:
const fetchData = async function() { // ... };- async箭头函数:
const fetchData = async () => { // ... };4.3 定时器函数
- setTimeout:
const timerId = setTimeout(() => { console.log('Delayed message'); }, 1000); clearTimeout(timerId); // 取消定时器- setInterval:
const intervalId = setInterval(() => { console.log('Repeating message'); }, 1000); clearInterval(intervalId); // 清除间隔- requestAnimationFrame:
function animate() { // 动画逻辑 requestAnimationFrame(animate); } requestAnimationFrame(animate);5. 实用函数与技巧
5.1 类型检查函数
- 基本类型检查:
typeof 42; // 'number' typeof 'str'; // 'string' typeof true; // 'boolean' typeof undefined; // 'undefined' typeof null; // 'object' (历史遗留问题) typeof {}; // 'object' typeof []; // 'object' typeof function(){}; // 'function'- 更精确的类型检查:
Object.prototype.toString.call([]); // '[object Array]' Object.prototype.toString.call(null); // '[object Null]' Array.isArray([]); // true- 自定义类型检查:
function isPlainObject(obj) { return Object.prototype.toString.call(obj) === '[object Object]' && Object.getPrototypeOf(obj) === Object.prototype; }5.2 实用工具函数
- 深度克隆:
function deepClone(obj) { if (obj === null || typeof obj !== 'object') return obj; const clone = Array.isArray(obj) ? [] : {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { clone[key] = deepClone(obj[key]); } } return clone; }- 对象合并:
function deepMerge(target, source) { for (const key in source) { if (source.hasOwnProperty(key)) { if (typeof source[key] === 'object' && source[key] !== null) { if (!target[key]) target[key] = Array.isArray(source[key]) ? [] : {}; deepMerge(target[key], source[key]); } else { target[key] = source[key]; } } } return target; }- 函数执行时间测量:
function measureTime(fn) { return function(...args) { const start = performance.now(); const result = fn.apply(this, args); const end = performance.now(); console.log(`Execution time: ${end - start}ms`); return result; }; }5.3 函数式编程实用函数
- 管道函数:
function pipe(...fns) { return function(x) { return fns.reduce((acc, fn) => fn(acc), x); }; } const process = pipe( x => x + 1, x => x * 2, x => x - 3 ); process(5); // (5+1)*2-3 = 9- 偏函数应用:
function partial(fn, ...presetArgs) { return function(...laterArgs) { return fn(...presetArgs, ...laterArgs); }; } const add = (a, b) => a + b; const add5 = partial(add, 5); add5(3); // 8- 惰性求值函数:
function lazy(fn) { let result; let evaluated = false; return function() { if (!evaluated) { result = fn.apply(this, arguments); evaluated = true; } return result; }; } const expensiveCalc = lazy(() => { console.log('Calculating...'); return 42; }); expensiveCalc(); // 第一次调用会计算 expensiveCalc(); // 第二次直接返回缓存结果6. 浏览器环境特有函数
6.1 DOM操作函数
- 元素选择:
document.getElementById('id'); document.querySelector('.class'); document.querySelectorAll('div');- 元素创建与修改:
document.createElement('div'); element.textContent = 'text'; element.innerHTML = '<span>HTML</span>'; element.setAttribute('data-id', '123'); element.classList.add('active');- 事件处理:
element.addEventListener('click', handler); element.removeEventListener('click', handler); element.dispatchEvent(new Event('click'));6.2 BOM相关函数
- 窗口控制:
window.open(url, '_blank'); window.close(); window.scrollTo(x, y);- 存储相关:
localStorage.setItem('key', 'value'); localStorage.getItem('key'); sessionStorage.setItem('key', 'value');- 导航相关:
location.href = 'https://example.com'; location.reload(); history.pushState(state, title, url);6.3 网络请求函数
- Fetch API:
fetch(url, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error(error));- XMLHttpRequest(传统方式):
const xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.onload = function() { if (xhr.status === 200) console.log(xhr.responseText); }; xhr.send();- WebSocket:
const socket = new WebSocket('ws://example.com'); socket.onopen = () => socket.send('Hello'); socket.onmessage = event => console.log(event.data);7. Node.js环境特有函数
7.1 文件系统函数
- 回调风格:
const fs = require('fs'); fs.readFile('file.txt', 'utf8', (err, data) => { if (err) throw err; console.log(data); });- Promise风格:
const fs = require('fs').promises; fs.readFile('file.txt', 'utf8') .then(data => console.log(data)) .catch(err => console.error(err));- 同步风格:
const data = fs.readFileSync('file.txt', 'utf8');7.2 路径处理函数
- path模块:
const path = require('path'); path.join('/foo', 'bar', 'baz'); // '/foo/bar/baz' path.resolve('foo', 'bar'); // 绝对路径 path.dirname('/foo/bar/baz.txt'); // '/foo/bar' path.basename('/foo/bar/baz.txt'); // 'baz.txt' path.extname('baz.txt'); // '.txt'- URL处理:
const url = require('url'); const parsed = url.parse('https://example.com/path?query=123'); const myURL = new URL('https://example.com');7.3 进程控制函数
- process对象:
process.argv; // 命令行参数 process.env.NODE_ENV; // 环境变量 process.cwd(); // 当前工作目录 process.exit(1); // 退出进程- 子进程:
const { exec } = require('child_process'); exec('ls -la', (error, stdout, stderr) => { if (error) console.error(error); console.log(stdout); });- 定时器增强:
setImmediate(() => console.log('Immediate')); process.nextTick(() => console.log('Next tick'));8. 函数性能优化与调试
8.1 性能优化技巧
- 避免不必要的函数创建:
// 不好的做法 - 每次渲染都创建新函数 function Component() { return <button onClick={() => console.log('Click')}>Click</button>; } // 好的做法 - 使用useCallback或类方法 function Component() { const handleClick = useCallback(() => console.log('Click'), []); return <button onClick={handleClick}>Click</button>; }- 使用记忆化减少重复计算:
const memoized = memoize(expensiveCalculation); memoized('input1'); // 计算 memoized('input1'); // 从缓存读取- 批量操作DOM:
// 不好的做法 - 多次重排 elements.forEach(el => el.style.width = '100px'); // 好的做法 - 使用文档片段 const fragment = document.createDocumentFragment(); elements.forEach(el => { el.style.width = '100px'; fragment.appendChild(el); }); document.body.appendChild(fragment);8.2 函数调试技巧
- console的进阶用法:
console.time('label'); // 要测量的代码 console.timeEnd('label'); // 输出执行时间 console.table([{a:1, b:2}, {a:3, b:4}]); // 表格形式输出 console.group('Group'); console.log('Message inside group'); console.groupEnd();- debugger语句:
function problematicFunction() { debugger; // 执行到这里会暂停 // ... }- 错误追踪:
function trackError() { try { // 可能出错的代码 } catch (error) { console.error('Error:', error); console.trace(); // 打印调用栈 } }8.3 函数性能分析
- performance API:
performance.mark('start'); // 要测量的代码 performance.mark('end'); performance.measure('measureName', 'start', 'end'); const measure = performance.getEntriesByName('measureName')[0]; console.log(measure.duration); // 执行时间(毫秒)- 内存分析:
// 记录初始内存 const initialMemory = process.memoryUsage().heapUsed; // 执行代码后 const finalMemory = process.memoryUsage().heapUsed; console.log(`Memory used: ${finalMemory - initialMemory} bytes`);- CPU分析:
const profiler = require('v8-profiler-next'); profiler.startProfiling('profile1'); // 执行要分析的代码 const profile = profiler.stopProfiling('profile1'); profile.export().pipe(fs.createWriteStream('profile.cpuprofile'));9. 函数安全与最佳实践
9.1 函数安全注意事项
- 避免eval:
// 不安全 - 可能执行恶意代码 eval(userInput); // 替代方案 - 使用JSON.parse或Function构造函数 const data = JSON.parse(userInput); const func = new Function('a', 'b', 'return a + b');- 防止原型污染:
function safeMerge(target, source) { for (const key in source) { if (key !== '__proto__' && key !== 'constructor' && key !== 'prototype') { target[key] = source[key]; } } return target; }- 输入验证:
function processInput(input) { if (typeof input !== 'string') { throw new TypeError('Expected string input'); } // 处理输入 }9.2 函数设计最佳实践
- 单一职责原则:
// 不好的做法 - 函数做太多事情 function processUser(user) { validateUser(user); saveToDatabase(user); sendWelcomeEmail(user); updateAnalytics(user); } // 好的做法 - 拆分函数 function processUser(user) { validateUser(user); persistUser(user); notifyUser(user); trackUser(user); }- 合理的参数数量:
// 不好的做法 - 参数太多 function createUser(name, email, password, age, gender, address, phone) {} // 好的做法 - 使用对象参数 function createUser({name, email, password, ...details}) {}- 明确的返回值:
// 不好的做法 - 不一致的返回类型 function getUser(id) { if (!id) return false; return {id, name: 'John'}; } // 好的做法 - 一致的返回类型 function getUser(id) { if (!id) return null; return {id, name: 'John'}; }9.3 错误处理策略
- 错误优先回调:
function asyncOperation(callback) { someAsyncTask((err, result) => { if (err) return callback(err); callback(null, processResult(result)); }); }- Promise错误处理:
asyncFunction() .then(result => processResult(result)) .catch(error => handleError(error)) .finally(() => cleanup());- async/await错误处理:
async function run() { try { const result = await asyncFunction(); return processResult(result); } catch (error) { handleError(error); } finally { cleanup(); } }10. 现代JavaScript新特性函数
10.1 ES6+新增函数特性
- 默认参数:
function greet(name = 'Guest') { console.log(`Hello, ${name}!`); }- 剩余参数:
function sum(...numbers) { return numbers.reduce((acc, num) => acc + num, 0); }- 解构参数:
function printUser({name, age}) { console.log(`${name} is ${age} years old`); }10.2 ES2017新增函数
- Object.values/Object.entries:
const obj = {a:1, b:2}; Object.values(obj); // [1,2] Object.entries(obj); // [['a',1],['b',2]]- 字符串填充函数:
'hello'.padStart(10, '*'); // '*****hello' 'hello'.padEnd(10, '*'); // 'hello*****'- 函数参数尾逗号:
function foo( param1, param2, // 允许尾逗号 ) {}10.3 ES2018新增函数特性
- 异步迭代:
async function process(array) { for await (const item of array) { await doSomething(item); } }- Rest/Spread属性:
const obj = {a:1, b:2, c:3}; const {a, ...rest} = obj; // rest = {b:2, c:3} const newObj = {...obj, d:4}; // {a:1, b:2, c:3, d:4}- Promise.finally:
fetch(url) .then(response => response.json()) .catch(error => console.error(error)) .finally(() => stopLoading());10.4 ES2019新增函数
- Array.flat/flatMap:
[1,[2,[3]]].flat(2); // [1,2,3] [1,2,3].flatMap(x => [x, x*2]); // [1,2,2,4,3,6]- Object.fromEntries:
Object.fromEntries([['a',1],['b',2]]); // {a:1, b:2}- 字符串trim方法:
' hello '.trimStart(); // 'hello ' ' hello '.trimEnd(); // ' hello'10.5 ES2020+新增函数
- 可选链操作符:
const name = user?.profile?.name;- 空值合并运算符:
const value = input ?? 'default';- BigInt:
const bigNum = BigInt(Number.MAX_SAFE_INTEGER) + 1n;- 动态导入:
const module = await import('/modules/module.js');- 全局This:
const global = globalThis; // 浏览器中是window,Node中是global- Promise.allSettled:
Promise.allSettled([promise1, promise2]) .then(results => { results.forEach(result => { if (result.status === 'fulfilled') console.log(result.value); else console.error(result.reason); }); });- String.matchAll:
const regexp = /t(e)(st(\d?))/g; const str = 'test1test2'; const matches = [...str.matchAll(regexp)];- 逻辑赋值运算符:
a ||= b; // a = a || b a &&= b; // a = a && b a ??= b; // a = a ?? b- 数字分隔符:
const billion = 1_000_000_000;- WeakRef和FinalizationRegistry:
const weakRef = new WeakRef(targetObject); const registry = new FinalizationRegistry(heldValue => { console.log(`${heldValue} was garbage collected`); }); registry.register(targetObject, 'some value');