第二部分:基础知识 6.函数 --[JavaScript 新手村:开启编程之旅的第一步]

news2025/1/16 10:28:59

JavaScript 函数是可重用的代码块,用于执行特定任务。函数可以接受参数(输入数据),并且可以返回一个值。JavaScript 提供了多种定义函数的方式,下面将详细介绍这些方式,并给出一些示例。

1. 函数声明

下面是两个使用 JavaScript 函数声明的示例。函数声明是通过 function 关键字定义的,并且它们具有提升(hoisting)特性,这意味着你可以在它们被定义之前调用这些函数。

示例 1: 简单的问候函数

这个例子展示了如何创建一个简单的函数来问候用户,并在控制台打印出问候语。

// 函数声明:greet
function greet(name) {
    return `Hello, ${name}!`;
}

// 调用函数
console.log(greet('Alice')); // 输出: Hello, Alice!

在这里插入图片描述

在这个例子中,我们定义了一个名为 greet 的函数,它接受一个参数 name,并返回一条包含该名字的问候信息。然后我们在控制台输出了调用此函数的结果。

示例 2: 计算圆的面积

这个例子展示了一个稍微复杂一点的函数,用于根据给定的半径计算圆的面积。

// 函数声明:calculateCircleArea
function calculateCircleArea(radius) {
    if (radius < 0) {
        return 'Radius cannot be negative.';
    }
    return Math.PI * radius * radius;
}

// 调用函数并处理不同情况
console.log(calculateCircleArea(5)); // 输出: 78.53981633974483
console.log(calculateCircleArea(-3)); // 输出: Radius cannot be negative.

在这里插入图片描述

在这个例子中,我们定义了一个名为 calculateCircleArea 的函数,它接受一个参数 radius,即圆的半径。函数首先检查半径是否为负数,如果是,则返回错误消息;否则,它将计算并返回圆的面积。我们还展示了如何处理不同的输入情况。

这两个例子说明了函数声明的基本用法及其提升特性。你可以在这两个例子的基础上扩展功能,添加更多的逻辑或参数以满足特定的需求。

2. 函数表达式

下面是两个使用 JavaScript 函数表达式的示例。函数表达式是将函数赋值给一个变量、属性或作为另一个函数的参数传递。与函数声明不同,函数表达式不会被提升,因此必须在定义之后调用。

示例 1: 使用匿名函数表达式

这个例子展示了如何创建一个匿名函数表达式,并通过赋值给变量来调用它。

// 函数表达式:greet
const greet = function(name) {
    return `Hello, ${name}!`;
};

// 调用函数表达式
console.log(greet('Alice')); // 输出: Hello, Alice!

在这里插入图片描述

在这个例子中,我们创建了一个匿名函数,并将其赋值给了名为 greet 的常量。然后我们像调用普通函数一样调用了 greet,并传入了参数 'Alice',结果是在控制台输出了一条问候信息。

示例 2: 使用命名函数表达式

有时候你可能想要给函数表达式一个名字,这被称为命名函数表达式。命名函数表达式不仅可以在外部通过变量名调用,还可以在函数内部通过名称进行递归调用。

// 命名函数表达式:factorial
const factorial = function fact(n) {
    if (n <= 1) {
        return 1;
    }
    return n * fact(n - 1);
};

// 调用命名函数表达式
console.log(factorial(5)); // 输出: 120

在这里插入图片描述

在这个例子中,我们创建了一个名为 factorial 的变量,并将其赋值为一个带有名称 fact 的函数表达式。这个函数用于计算阶乘(factorial)。注意,虽然我们通过 factorial 变量调用了函数,但在函数体内部,我们可以使用名称 fact 来实现递归调用。

这两个例子展示了如何使用函数表达式来定义和调用函数。函数表达式特别适合那些需要动态创建函数或者将函数作为参数传递给其他函数的情况。此外,命名函数表达式还提供了更好的调试支持和递归调用的可能性。

3. 箭头函数 (ES6+)

下面是两个使用 JavaScript 箭头函数(Arrow Function)的示例。箭头函数提供了一种更简洁的语法来定义函数,并且在处理 this 关键字时有不同的行为,通常更适合用作短小、简单的函数。

示例 1: 简单的箭头函数

这个例子展示了如何创建一个简单的箭头函数来执行基本操作,比如问候用户。

// 箭头函数:greet
const greet = (name) => {
    return `Hello, ${name}!`;
};

// 如果函数体只有一行,可以省略大括号和 return 关键字
const quickGreet = name => `Hi, ${name}!`;

// 调用箭头函数
console.log(greet('Alice')); // 输出: Hello, Alice!
console.log(quickGreet('Bob')); // 输出: Hi, Bob!

在这里插入图片描述

在这个例子中,我们定义了两个箭头函数 greetquickGreetgreet 使用了完整的形式,而 quickGreet 展示了当函数体只有一行时如何简化代码。两者都接受一个参数 name 并返回一条问候信息。

示例 2: 使用箭头函数处理数组方法

这个例子展示了如何结合箭头函数与数组的方法(如 mapfilter),以一种更加简洁的方式进行数据处理。

// 数据集
const numbers = [1, 2, 3, 4, 5, 6];

// 使用箭头函数进行映射操作
const squaredNumbers = numbers.map(num => num * num);

// 使用箭头函数进行过滤操作
const evenNumbers = numbers.filter(num => num % 2 === 0);

// 输出结果
console.log(squaredNumbers); // 输出: [1, 4, 9, 16, 25, 36]
console.log(evenNumbers); // 输出: [2, 4, 6]

在这里插入图片描述

在这个例子中,我们首先定义了一个数字数组 numbers。然后,我们使用箭头函数与数组的 map 方法相结合,创建了一个新的数组 squaredNumbers,其中每个元素都是原数组元素的平方。接着,我们使用 filter 方法和箭头函数来筛选出所有的偶数,并将它们存储在 evenNumbers 数组中。

这两个例子展示了箭头函数如何简化代码并提高可读性,特别是在处理简短逻辑或与数组方法结合使用时。箭头函数非常适合用于不需要改变 this 上下文的场景,如回调函数或表达式函数。此外,由于其简洁的语法,箭头函数也常用于需要频繁定义小型函数的地方。

4. 构造函数

下面是两个使用 JavaScript 构造函数的示例。构造函数是一种特殊的函数,主要用于创建和初始化对象实例。它们通常以大写字母开头,并通过 new 关键字来调用。

示例 1: 创建一个简单的 Person 构造函数

这个例子展示了如何定义一个简单的构造函数来创建 Person 对象实例,并为这些实例添加属性和方法。

// 定义构造函数:Person
function Person(name, age) {
    this.name = name;
    this.age = age;
}

// 为所有 Person 实例添加一个方法 greet
Person.prototype.greet = function() {
    console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
};

// 使用 new 关键字创建 Person 的实例
const alice = new Person('Alice', 30);
const bob = new Person('Bob', 25);

// 调用实例的方法
alice.greet(); // 输出: Hello, my name is Alice and I'm 30 years old.
bob.greet();   // 输出: Hello, my name is Bob and I'm 25 years old.

在这里插入图片描述

在这个例子中,我们定义了一个名为 Person 的构造函数,它接受两个参数 nameage 并将它们赋值给新对象的相应属性。然后,我们在 Person.prototype 上添加了一个 greet 方法,这样所有的 Person 实例都可以访问这个方法。最后,我们使用 new 关键字创建了两个 Person 的实例 alicebob,并调用了它们的 greet 方法。

示例 2: 创建一个更复杂的 Book 构造函数

这个例子展示了如何定义一个更复杂的构造函数 Book,包括初始化属性、添加实例方法以及处理私有变量。

// 定义构造函数:Book
function Book(title, author, year) {
    // 公共属性
    this.title = title;
    this.author = author;
    this.year = year;

    // 私有变量(闭包中的局部变量)
    let publicationYear = year;

    // 实例方法
    this.getSummary = function() {
        return `${this.title} was written by ${this.author} in ${publicationYear}.`;
    };

    // 修改出版年份的方法(保护私有变量)
    this.updateYear = function(newYear) {
        publicationYear = newYear;
    };
}

// 使用 new 关键字创建 Book 的实例
const book1 = new Book('The Great Gatsby', 'F. Scott Fitzgerald', 1925);

// 调用实例的方法
console.log(book1.getSummary()); // 输出: The Great Gatsby was written by F. Scott Fitzgerald in 1925.

// 更新出版年份
book1.updateYear(1930);
console.log(book1.getSummary()); // 输出: The Great Gatsby was written by F. Scott Fitzgerald in 1930.

在这里插入图片描述

在这个例子中,我们定义了一个名为 Book 的构造函数,它不仅设置了公共属性 titleauthoryear,还通过闭包创建了一个私有变量 publicationYear 来存储书籍的实际出版年份。我们为每个 Book 实例添加了两个方法:getSummary 返回书籍的摘要信息,而 updateYear 则允许更新私有变量 publicationYear 的值。这展示了如何在构造函数中实现属性封装和方法定义。

这两个例子说明了如何使用构造函数来创建自定义对象类型,并为其添加属性和方法。构造函数是面向对象编程的基础之一,提供了强大的工具来组织代码和管理复杂的数据结构。

5. 立即执行函数表达式 (IIFE)

立即执行函数表达式(IIFE, Immediately Invoked Function Expression)是一种在定义后立即执行的匿名函数。IIFE 常用于创建独立的作用域,避免全局命名空间污染,并且可以封装变量和函数,使其不会影响或被外部环境所影响。

下面是一个使用 IIFE 的示例,它展示了如何创建一个封闭的作用域来执行一些代码,并返回结果。

示例:使用 IIFE 计算并打印斐波那契数列

// 定义并立即执行的函数表达式 (IIFE)
(function fibonacci(n) {
    let result = [];
    let a = 0, b = 1;

    for (let i = 0; i < n; i++) {
        result.push(a);
        [a, b] = [b, a + b];
    }

    console.log(`Fibonacci sequence of ${n} numbers:`, result);
})(10); // 传递参数 10 给 IIFE

在这里插入图片描述

解释:
  • 定义 IIFE:

    • 使用 function 关键字定义一个匿名函数。
    • 立即将这个匿名函数用括号 () 包裹起来,形成一个表达式。
    • 在最后添加另一对括号 () 来调用这个函数,并可以在此处传递参数。
  • 函数体:

    • 在这个例子中,我们定义了一个简单的循环来生成斐波那契数列,并将结果存储在一个数组 result 中。
    • 使用解构赋值 [a, b] = [b, a + b] 来更新序列中的两个连续数字。
  • 执行与输出:

    • 函数被立即执行,并计算前 10 个斐波那契数。
    • 使用 console.log 输出这些数到控制台。

这个例子展示了 IIFE 的基本结构和用途。通过将代码封装在一个立即执行的函数中,我们可以确保任何在函数内部声明的变量和函数都不会泄漏到全局作用域中,从而保持代码的干净和模块化。此外,IIFE 还可以在需要时接收参数,如上面的例子所示,使得它可以灵活地根据传入的参数执行不同的逻辑。

另一种 IIFE 的写法

有时你可能会看到 IIFE 写成如下形式,这也是一种有效的写法:

(function() {
    console.log('This message will only be shown once.');
})();

这种写法同样有效,但是为了明确地表示函数表达式接受参数,通常推荐使用第一种形式,即在包裹匿名函数的括号内定义参数。

6. 异步函数 (Async/Await)

当然,下面是一个使用 JavaScript 异步函数(async/await)的示例。异步函数允许你以同步的方式编写异步代码,简化了处理 Promise 的复杂性,并且使代码更易读、更易于维护。

示例:使用 asyncawait 模拟数据获取

在这个例子中,我们将创建一个模拟从服务器获取用户数据的过程,并使用 async/await 来处理这个异步操作。

// 模拟API请求的函数,返回一个Promise
function mockApiRequest(userId) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (userId > 0) {
                resolve({ id: userId, name: `User ${userId}` });
            } else {
                reject(new Error('Invalid user ID'));
            }
        }, 1000); // 模拟网络延迟1秒
    });
}

// 定义一个异步函数来获取用户数据
async function fetchUserData(userId) {
    try {
        console.log('Fetching user data...');
        const userData = await mockApiRequest(userId);
        console.log('User data received:', userData);
        return userData;
    } catch (error) {
        console.error('Error fetching user data:', error.message);
    }
}

// 调用异步函数并处理结果
fetchUserData(1)
    .then(user => console.log('Final result:', user))
    .catch(error => console.error('Final error:', error));

// 模拟调用带有无效ID的情况
fetchUserData(-1);

在这里插入图片描述

解释:
  • mockApiRequest:

    • 这个函数模拟了一个 API 请求,它接受一个 userId 参数,并返回一个 Promise
    • 如果 userId 大于 0,则在模拟的网络延迟(1秒)后解析为包含用户信息的对象;否则,拒绝该 Promise 并抛出错误。
  • fetchUserData:

    • 使用 async 关键字定义的异步函数。
    • 函数内部使用 await 等待 mockApiRequest 返回的结果。
    • 如果 mockApiRequest 成功解析,那么它将打印接收到的用户数据,并返回该数据。
    • 如果 mockApiRequest 抛出错误,则通过 catch 块捕获错误并打印错误信息。
  • 调用异步函数:

    • 我们调用了 fetchUserData 函数两次,一次使用有效的 userId(即 1),另一次使用无效的 userId(即 -1)。
    • 对于有效的 userId,我们还展示了如何使用 .then() 方法处理最终结果。
    • 对于无效的 userId,我们可以看到错误被捕获并在控制台中输出。

这个例子展示了如何使用 async/await 来简化异步编程。它使得异步代码看起来和行为上更像是同步代码,从而提高了代码的可读性和可维护性。同时,通过 try...catch 结构,可以方便地处理可能发生的错误。

函数参数默认值 (ES6+)

从 ES6 开始,JavaScript 支持为函数参数设置默认值。

function multiply(a, b = 1) {
    return a * b;
}

console.log(multiply(5)); // 输出: 5
console.log(multiply(5, 3)); // 输出: 15

在这里插入图片描述

Rest 参数与 Spread 语法 (ES6+)

Rest 参数允许你表示不确定数量的参数为一个数组,而 Spread 语法则允许你扩展可迭代对象。

function sum(...args) {
    return args.reduce((acc, curr) => acc + curr, 0);
}

console.log(sum(1, 2, 3, 4)); // 输出: 10

const numbers = [1, 2, 3];
console.log(sum(...numbers, 4)); // 输出: 10

在这里插入图片描述

这些是 JavaScript 中定义和使用函数的一些基本方式。每种方式都有其适用场景,理解它们的区别和优势可以帮助你写出更加高效、可维护的代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2256515.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

我眼中的“懂重构”(一)

初识重构 2017年的时候&#xff0c;领导让我看公司的一本书《重构——改善代码的既有设计》&#xff0c;这是一本JAVA版本的&#xff0c;前后看了2遍。那时候看书因为不懂看的格外仔细。我只是那时候不懂&#xff0c;然而多年后的今天我仍然发现很多人对重构充满误解。在刚进入…

机器学习详解(3):线性回归之代码详解

文章目录 1 数据预处理2 构建线性回归模型并绘制回归线初始化方法前向传播&#xff1a;forward_propagation代价函数&#xff1a;cost_function反向传播&#xff1a;backward_propagation参数更新&#xff1a;update_parameters训练方法&#xff1a;train代码运行结果 3 使用Py…

基于openzeppelin插件的智能合约升级

一、作用以及优点 部署可升级合约&#xff0c;插件自动部署proxy和proxyAdmin合约&#xff0c;帮助管理合约升级和交互&#xff1b;升级已部署合约&#xff0c;通过插件快速升级合约&#xff0c;脚本开发方便快捷&#xff1b;管理代理管理员的权限&#xff0c;只有proxyAdmin的…

游戏引擎学习第36天

仓库 :https://gitee.com/mrxiao_com/2d_game 回顾之前的内容 在这个程序中&#xff0c;目标是通过手动编写代码来从头开始制作一个完整的游戏。整个过程不使用任何库或现成的游戏引擎&#xff0c;这样做的目的是为了能够全面了解游戏执行的每一个细节。开发过程中&#xff0…

试题转excel;pdf转excel;试卷转Excel,word试题转excel

一、问题描述 一名教师朋友&#xff0c;偶尔会需要整理一些高质量的题目到excel中 以往都是手动复制搬运&#xff0c;几百道题几乎需要一个下午的时间 关键这些事&#xff0c;枯燥无聊费眼睛&#xff0c;实在是看起来就很蠢的工作 就想着做一个工具&#xff0c;可以自动处理…

16-01、JVM系列之:内存与垃圾回收篇(一)

JVM系列之&#xff1a;内存与垃圾回收篇&#xff08;一&#xff09; ##本篇内容概述&#xff1a; 1、JVM结构 2、类加载子系统 3、运行时数据区之&#xff1a;PC寄存器、Java栈、本地方法栈一、JVM与JAVA体系结构 JAVA虚拟机与JAVA语言并没有必然的联系&#xff0c;它只是与特…

2030. gitLab A仓同步到B仓

文章目录 1 A 仓库备份 到 B 仓库2 B 仓库修改main分支的权限 1 A 仓库备份 到 B 仓库 #!/bin/bash# 定义变量 REPO_DIR"/home/xhome/opt/git_sync/zz_xx_xx" # 替换为你的本地库A的实际路径 REMOTE_ORIGIN"http://192.168.1.66:8181/zzkj_software/zz_xx_xx.…

服务器上部署前端页面-实现IP+端口/index.html在线访问你的网页

首先一点&#xff0c;不管是那个框架开发的网页前端&#xff0c;最后都需要Build,构建完毕以后都是原始的HTML CSS JS 三样文件&#xff01; 所以不管用原始的三剑客&#xff08;HTML CSS JS&#xff09;开发的前端还是用各类框架开发的前端界面&#xff08;只是让开发简单…

树莓派 PICO RP2040 MACOS 使用

文章参考&#xff1a; Developing in C on the RP2040: macOS | Wellys Dev 这里会提示报错&#xff1a;ln: /bin/picotool: Operation not permitted 参考&#xff1a;Mac ln命令报错&#xff1a;Operation not permitted_ln operation not permitted-CSDN博客 放在 usr/lo…

顶顶通电话机器人开发接口对接大语言模型之实时流TTS对接介绍

大语言模型一般都是流式返回文字&#xff0c;如果等全部文字返回了一次性去TTS&#xff0c;那么延迟会非常严重&#xff0c;常用的方法就是通过标点符号断句&#xff0c;返回了一句话就提交给TTS。随着流TTS的出现&#xff0c;就可以直接把大模型返回的文字灌给流TTS&#xff0…

git使用-创建本地仓库、绑定远程仓库

文章目录 1. 创建git仓库2. commit提交到本地3. 创建远程仓库4. 关联远程仓库5. push代码至远程仓库6. 完成初始化 git作为版本控制工具&#xff0c;在开发过程中经常使用到。这里以github为例&#xff0c;简单介绍下仓库的创建及绑定&#xff0c;方便忘记了能快速的想起来。 1…

JavaScript 中通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能,JS中排序算法的使用详解(附实际应用代码)

目录 JavaScript 中通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能&#xff0c;JS中排序算法的使用详解&#xff08;附实际应用代码&#xff09; 一、为什么要使用Array.sort() 二、Array.sort() 的使用与技巧 1、基础语法 2、返回值 3、…

为什么Unity里的变体数和UWA工具测出来的不一样

1&#xff09;为什么Unity里的变体数和UWA工具测出来的不一样 2&#xff09;使用TextureArray为什么会导致L1 Cache Miss率变高 3&#xff09;Gfx.PresentFrame耗时异常高 4&#xff09;AO方案中哪个更适合移动端 这是第412篇UWA技术知识分享的推送&#xff0c;精选了UWA社区的…

汽车免拆案例 | 2007款宝马650i车发动机偶尔无法起动

故障现象 一辆2007款宝马650i车&#xff0c;搭载N62B48B发动机&#xff0c;累计行驶里程约为26万km。车主反映&#xff0c;发动机偶尔无法起动&#xff0c;故障频率较低&#xff0c;十几天出现1 次&#xff0c;且故障出现时起动机不工作。 故障诊断  接车后试车&#xff0c;…

DataEase 是开源的 BI 工具

DataEase 是开源的 BI 工具&#xff0c;帮助用户快速分析数据并洞察业务趋势&#xff0c;从而实现业务的改进与优化。DataEase 支持丰富的数据源连接&#xff0c;能够通过拖拉拽方式快速制作图表&#xff0c; DataEase 的优势&#xff1a; 开源开放&#xff1a;零门槛&#xf…

【C#设计模式(17)——迭代器模式(Iterator Pattern)】

前言 迭代器模式可以使用统一的接口来遍历不同类型的集合对象&#xff0c;而不需要关心其内部的具体实现。 代码 //迭代器接口 public interface Iterator {bool HashNext();object Next(); } //集合接口 public interface Collection {Iterator CreateIterator(); } //元素迭…

在LabVIEW中如何利用FPGA提升算法性能

在LabVIEW中利用FPGA的性能进行算法开发&#xff0c;能极大提升数据处理和实时计算的速度。LabVIEW提供了针对FPGA的开发工具&#xff0c;如LabVIEW FPGA Module&#xff0c;可以使开发者将算法部署到FPGA硬件上&#xff0c;从而实现并行计算和低延迟操作。以下是如何在LabVIEW…

Day7 苍穹外卖项目 缓存菜品、SpringCache框架、缓存套餐、添加购物车、查看购物车、清空购物车

目录 1.缓存菜品 1.1 问题说明 1.2 实现思路 1.3 代码开发 1.3.1 加入缓存 1.3.2 清除缓存 1.3.2.1 新增菜品优化 1.3.2.2 菜品批量删除优化 1.3.2.3 修改菜品优化 1.3.2.4 菜品起售停售优化 1.4 功能测试 1.4.1 加入缓存 1.4.2 菜品修改 1.5 代码提交 2.缓存套餐 2.1 Spring C…

HCIA-openGauss_2_2连接与认证

设置客户端认证策略 设置配置文件参数 gssql客户端连接-确定连接信息 客户端工具通过数据库主节点连接数据库&#xff0c;因此连接前&#xff0c;需要获取数据库主节点的在服务器的IP地址及数据库主节点的端口号信息。 步骤1&#xff1a;以操作系统用户omm登录数据库主节点。…

上海理工大学《2024年867自动控制原理真题》 (完整版)

本文内容&#xff0c;全部选自自动化考研联盟的&#xff1a;《上海理工大学867自控考研资料》的真题篇。后续会持续更新更多学校&#xff0c;更多年份的真题&#xff0c;记得关注哦~ 目录 2024年真题 Part1&#xff1a;2024年完整版真题 2024年真题