当前位置: 首页 > news >正文

Node.js入门教程(二十一):函数

一、函数的重要性

函数是一段可重复使用的代码块,用于执行特定任务。

在 Node.js 中,函数是 JavaScript 的核心组成部分之一,是构建应用程序的基本单元。

Node.js 继承了 JavaScript 的所有函数特性,并在其异步编程模型中发挥了重要作用。

在 JavaScript 中,一个函数可以作为另一个函数的参数。我们可以先定义一个函数,然后传递,也可以在传递参数的地方直接定义函数。

函数的重要性

方面说明
代码复用避免重复编写相同逻辑
模块化将复杂问题分解为小函数
可维护性便于调试和修改独立功能单元

二、函数定义方式

函数声明

使用function关键字声明一个函数:

function greet(name) { console.log(`Hello, ${name}!`); }

函数表达式

将函数赋值给一个变量:

const greet = function(name) { console.log(`Hello, ${name}!`); };

箭头函数

ES6 引入的简洁函数表达式:

const greet = (name) => { console.log(`Hello, ${name}!`); }; // 单行箭头函数(可省略 return) const greet = name => console.log(`Hello, ${name}!`); // 返回对象的箭头函数需要加括号 const getUser = () => ({ name: 'Alice', age: 30 });

三、函数的类型

1. 普通函数

最常见的函数形式,可以有参数和返回值:

function add(a, b) { return a + b; }

2. 匿名函数

没有名字的函数,通常作为参数传递给其他函数:

setTimeout(function() { console.log('This is an anonymous function.'); }, 1000);

3. 回调函数

作为参数传递给另一个函数,并在某个操作完成后被调用:

function fetchData(callback) { setTimeout(() => { const data = 'Some data'; callback(data); }, 1000); } fetchData((data) => { console.log(data); });

四、异步函数

从回调到 Promise

const fs = require('fs'); function readFilePromise(path) { return new Promise((resolve, reject) => { fs.readFile(path, 'utf8', (err, data) => { if (err) reject(err); else resolve(data); }); }); }

async/await

使用asyncawait关键字处理异步操作:

async function fetchUser(id) { try { const response = await fetch(`https://api.example.com/users/${id}`); const user = await response.json(); return user; } catch (error) { console.error('Error fetching user:', error); } } fetchUser(1).then(user => console.log(user));

五、调用方式对比

调用方式示例特点
直接调用greet('Alice')最常见的方式
作为方法调用obj.method()this指向调用对象
构造函数调用new Constructor()创建新实例
间接调用greet.call(null, 'Bob')可改变this指向

六、高级用法

1. 闭包

闭包是指一个函数能够记住并访问其词法作用域,即使这个函数在其词法作用域之外执行:

function createCounter() { let count = 0; return function() { count++; return count; }; } const counter = createCounter(); console.log(counter()); // 1 console.log(counter()); // 2

2. 高阶函数

接受函数作为参数或返回函数的函数:

function applyOperation(a, b, operation) { return operation(a, b); } const sum = applyOperation(5, 3, (x, y) => x + y); const product = applyOperation(5, 3, (x, y) => x * y); console.log(sum); // 8 console.log(product); // 15

七、函数参数处理

默认参数

在函数声明时为参数提供默认值:

function greet(name = 'Guest') { console.log(`Hello, ${name}!`); } greet(); // Hello, Guest! greet('Alice'); // Hello, Alice!

剩余参数

允许将不定数量的参数表示为一个数组:

function sum(...numbers) { return numbers.reduce((acc, num) => acc + num, 0); } console.log(sum(1, 2, 3, 4)); // 10

解构参数

从对象或数组中提取数据并将其赋值给变量:

function getUserInfo({ name, age }) { console.log(`Name: ${name}, Age: ${age}`); } const user = { name: 'Alice', age: 30 }; getUserInfo(user); // Name: Alice, Age: 30

八、函数作为参数传递

在 Node.js 中,函数可以作为参数传递给其他函数:

function say(word) { console.log(word); } function execute(someFunction, value) { someFunction(value); } execute(say, "Hello");

以上代码中,我们把say函数作为execute函数的第一个变量进行了传递。这里传递的不是say的返回值,而是say本身!

这样一来,say就变成了execute中的本地变量someFunctionexecute可以通过调用someFunction()(带括号的形式)来使用say函数。

匿名函数

我们可以把一个函数作为变量传递,但不一定要"先定义,再传递",可以直接在另一个函数的括号中定义和传递:

function execute(someFunction, value) { someFunction(value); } execute(function(word) { console.log(word); }, "Hello");

我们在execute接受第一个参数的地方直接定义了我们准备传递给execute的函数。用这种方式,我们甚至不用给这个函数起名字,这也是为什么它被叫做匿名函数

九、函数是如何让 HTTP 服务器工作的

带着这些知识,再来看看简约而不简单的 HTTP 服务器:

var http = require("http"); http.createServer(function(request, response) { response.writeHead(200, {"Content-Type": "text/plain"}); response.write("Hello World"); response.end(); }).listen(8888);

现在它看上去应该清晰了很多:我们向createServer函数传递了一个匿名函数

用这样的代码也可以达到同样的目的:

var http = require("http"); function onRequest(request, response) { response.writeHead(200, {"Content-Type": "text/plain"}); response.write("Hello World"); response.end(); } http.createServer(onRequest).listen(8888);

十、函数最佳实践

函数设计原则

原则说明
单一职责一个函数只做一件事
合理命名使用动词+名词形式(如getUserInfo
控制长度建议不超过 20 行代码
避免副作用纯函数更易于测试和维护

示例:单一职责

function calculateArea(width, height) { return width * height; }

示例:避免全局变量

function calculateTotal(items) { let total = 0; for (const item of items) { total += item.price * item.quantity; } return total; }

使用箭头函数

箭头函数简洁明了,特别是在处理回调函数时:

const users = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]; const names = users.map(user => user.name); console.log(names); // ['Alice', 'Bob']

错误处理

使用try...catch语句处理可能抛出的错误:

async function fetchUser(id) { try { const response = await fetch(`https://api.example.com/users/${id}`); if (!response.ok) { throw new Error('Network response was not ok'); } const user = await response.json(); return user; } catch (error) { console.error('Error fetching user:', error); } }

十一、性能优化技巧

使用闭包缓存结果(记忆化)

function memoize(fn) { const cache = new Map(); return (...args) => { const key = JSON.stringify(args); if (cache.has(key)) return cache.get(key); const result = fn(...args); cache.set(key, result); return result; }; } // 使用 const slowFibonacci = memoize(function(n) { if (n < 2) return n; return slowFibonacci(n - 1) + slowFibonacci(n - 2); });

十二、实战练习

练习 1:温度转换函数

/** * 实现摄氏度和华氏度互相转换 * @param {number} temp - 温度值 * @param {string} unit - 原始单位 ('C' 或 'F') * @returns {number} 转换后的温度 */ function convertTemperature(temp, unit) { if (unit === 'C') { return temp * 9 / 5 + 32; // 摄氏转华氏 } else if (unit === 'F') { return (temp - 32) * 5 / 9; // 华氏转摄氏 } throw new Error('Invalid unit. Use "C" or "F".'); } console.log(convertTemperature(0, 'C')); // 32 console.log(convertTemperature(32, 'F')); // 0

练习 2:简单的事件发射器

class EventEmitter { constructor() { this.events = {}; } // 注册事件监听 on(event, listener) { if (!this.events[event]) { this.events[event] = []; } this.events[event].push(listener); return this; } // 触发事件 emit(event, ...args) { if (!this.events[event]) return false; this.events[event].forEach(listener => { listener(...args); }); return true; } // 移除事件监听 off(event, listener) { if (!this.events[event]) return this; this.events[event] = this.events[event].filter( l => l !== listener ); return this; } // 一次性监听 once(event, listener) { const wrapper = (...args) => { listener(...args); this.off(event, wrapper); }; return this.on(event, wrapper); } } // 使用示例 const emitter = new EventEmitter(); emitter.on('greet', (name) => { console.log(`Hello, ${name}!`); }); emitter.emit('greet', 'Alice'); // Hello, Alice!

十三、本章小结

知识点说明
函数定义函数声明、函数表达式、箭头函数
函数类型普通函数、匿名函数、回调函数
异步函数Promise、async/await
高级用法闭包、高阶函数
参数处理默认参数、剩余参数、解构参数
函数作为参数回调函数、匿名函数
最佳实践单一职责、合理命名、错误处理

提示:函数是 JavaScript/Node.js 的核心构建块。理解函数的不同形式、调用方式和高级用法,是编写高质量 Node.js 应用的基础。在实际开发中,建议优先使用箭头函数处理简单的回调逻辑,使用async/await处理异步操作,并始终遵循单一职责原则编写函数。

http://www.cnnetsun.cn/news/4006619.html

相关文章:

  • 揭秘温州网站建设哪家好?资深专家教你避开陷阱打造高转化官网
  • 宜宾网站建设公司深度解析:为何选择合适的宜宾网站建设公司是决定企业数字化转型成败的关键?
  • PuzzleJs碎片(Fragment)开发实战:4种类型及应用场景
  • 专业网站建设计划表如何制定:从0到1打造高转化网站的完整指南
  • PrimeFlex动画与过渡效果:从基础到高级应用
  • 2024年深度解析虚拟币网站建设:从冷启动到合规落地的实战避坑指南
  • 深度解析中国建设部官方网站在新时代建筑转型中的核心地位与价值
  • react-native-autolink源码解析:深入理解文本解析与链接生成机制
  • 拒绝套路与隐形收费,深度剖析南通网站建设外包的真实性价比与避坑指南
  • 深圳h5网站建设怎么做才能既美观又实用?老程序员掏心窝子分享避坑指南
  • 大连网站建设谁家好:避坑指南与真实案例揭秘,助你找到最靠谱的服务商
  • 揭秘泉州网站建设费用背后的真实逻辑,如何以合理预算打造高转化企业官网
  • 桂城网站建设指南:如何打造一款既接地气又高转化的企业官网
  • 揭秘阿克苏网站建设公司的幕后真相与行业黑幕
  • 在线购物网站建设:从零基础到爆单的实战指南与避坑心得
  • 避坑指南:如何甄别靠谱的全国网站建设公司并打造高转化官网
  • 终极指南:用MiniMax H3量化版轻松生成2K电影级视频
  • 淘客优惠券网站建设那些事儿:从0到1的草根突围与真心话
  • 商务网站建设的一般流程是什么意思
  • 深度解析中国建设银行官网网站及其数字化服务生态与未来展望
  • 揭秘php建设网站工具:为什么老程序员依然对PHP情有独钟?深度解析PHP建设网站工具的实际应用与未来趋势
  • 怎么进不了深圳市建设局网站(官方入口无法访问的五大排查方向)
  • 莱芜百度网站建设怎么做好?揭秘中小企业如何在搜索引擎获客并提升品牌形象的避坑指南
  • 苏州吴中长桥网站建设:如何让本地企业官网不只是“面子工程”而是真正的获客引擎
  • 揭秘:企业网站建设项目标书避坑指南与高质量撰写技巧
  • 旅游营销型网站建设:如何打造高转化率的在线获客引擎
  • asmcrypto.js安全实践:避免前端加密常见陷阱的终极方案
  • 3分钟网页变应用:PakePlus零代码打包终极指南
  • 商业网站建设软件如何选择:从0到1打造高转化率官网的实战避坑指南
  • 深入了解东莞建设网站的公司简介:如何挑选靠谱的技术团队与服务流程