深入理解函数【JavaScript】

news2024/11/16 11:38:44

在 JavaScript 中,函数作为一种重要的基本结构,承载着编程中的许多关键概念。下面是与函数相关的内容介绍:

1. 函数定义

JavaScript 中有多种方式定义函数:

1.1 函数声明(Function Declaration)

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

console.log(add(2, 3)); // 输出: 5

 

 

1.2 函数表达式(Function Expression)

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

console.log(multiply(4, 5)); // 输出: 20

 

1.3 箭头函数(Arrow Function)

const subtract = (a, b) => {
    return a - b;
};

console.log(subtract(10, 7)); // 输出: 3

// 简写形式(若只有一条语句和一个参数)
const square = x => x * x;

console.log(square(6)); // 输出: 36

 

1.4 命名函数表达式(Named Function Expression)

const divide = function division(a, b) {
    if (b === 0) {
        return '不能除以零';
    }
    return a / b;
};

console.log(divide(10, 2)); // 输出: 5
console.log(divide(10, 0)); // 输出: '不能除以零'

 

1.5 立即调用函数表达式(IIFE, Immediately Invoked Function Expression)

(function() {
    const message = 'Hello, World!';
    console.log(message);
})(); // 输出: 'Hello, World!'

 

1.6 使用参数默认值的箭头函数

const greet = (name = '陌生人') => {
    return `你好, ${name}!`;
};

console.log(greet('小明')); // 输出: '你好, 小明!'
console.log(greet()); // 输出: '你好, 陌生人!'

 

1.7 具名的IIFE

(function greet() {
    console.log('Hello, IIFE!');
})(); // 输出: 'Hello, IIFE!'

 

1.8 Function 构造函数 

const myFunction = new Function(arg1, arg2, ..., "functionBody");
  • arg1, arg2, ... 是参数的名称(作为字符串)。
  • "functionBody" 是一个字符串,包含了函数的主体。

以下是一个使用 Function 构造函数的示例:

// 创建一个简单的加法函数
const add = new Function('a', 'b', 'return a + b;');

console.log(add(2, 3)); // 输出: 5

 

 

2. 函数属性

2.1 内置属性

  • length: 表示函数定义时的参数个数。
function example(a, b) {}
console.log(example.length); // 输出: 2

 

  • name: 返回函数的名称。
function example() {}
console.log(example.name); // 输出: "example"

 

2.2 自定义属性

你可以为函数添加自定义属性,就像对待普通对象一样。例如:

function myFunction() {
    return "Hello";
}

myFunction.description = "这是一个简单的函数";
console.log(myFunction.description); // 输出: "这是一个简单的函数"

 

2.3  prototype 属性(重要!!!)

在 JavaScript 中,每个函数都有一个 prototype 属性。这个属性是一个对象,用以存放可以被该函数的实例共享的属性和方法。

下面是一个简单的示例,展示如何利用 prototype 属性来为构造函数添加方法:

function Person(name, age) {
				this.name = name;
				this.age = age;
			}

			// 添加方法到 Person 的原型
			Person.prototype.introduce = function() {
				console.log(`大家好,我是 ${this.name},我 ${this.age} 岁。`); // 输出: "大家好,我是 LuQian,我 18 岁。"
			};

			const alice = new Person("LuQian", 18);
			alice.introduce();
示例代码解析:
2.3.1 构造函数定义
function Person(name, age) {
    this.name = name;
    this.age = age;
}
  • 这是一个构造函数 Person,用于创建 Person 类型的对象。
  • name 和 age 是参数,用于初始化对象的属性。
  • 在函数体内,使用 this.name 和 this.age 将参数值赋给当前对象的 name 和 age 属性。
2.3.2 添加方法到原型
Person.prototype.introduce = function() {
    console.log(`大家好,我是 ${this.name},我 ${this.age} 岁。`);
};
  • 通过 Person.prototype 为 Person 类型的对象添加一个方法 introduce
  • 这个方法使用模板字符串(反引号)来格式化消息,打印出当前对象的名称和年龄。
  • 在这个方法中,this 关键字指向调用该方法的实例对象。
2.3.3 创建实例
const alice = new Person("LuQian", 18);
  • 使用 new 操作符调用 Person 构造函数,创建一个名为 alice 的新实例。
  • 传入参数 "LuQian" 和 18,因此 LuQian.name 将被赋值为 "LuQian"LuQian.age 将被赋值为 30
2.3.4 调用 introduce 方法
alice.introduce(); // 输出: "大家好,我是 LuQian,我 18 岁。"
  • 在 alice 对象上调用 introduce 方法。
  • 该方法打印出一个消息,内容包括 alice 的名字和年龄,输出结果为 "大家好,我是 LuQian,我 18 岁。"

3. 函数的调用方法

3.1 直接调用

直接通过函数名调用函数:

function sayHello() {
    console.log("Hello!");
}

sayHello(); // 输出: Hello!

 

3.2 方法调用

如果函数是对象的方法,则通过对象来调用:

const person = {
    name: "LuQian",
    greet: function() {
        console.log("Hello, " + this.name);
    }
};

person.greet(); // 输出: Hello, LuQian

3.3 构造函数调用

使用 new 关键字调用函数,通常用于创建对象:

function Person(name) {
    this.name = name;
}

const LuQian= new Person("LuQian");
console.log(LuQian.name); // 输出: LuQian

3.4 使用 call 和 apply

通过 call 和 apply 方法可以改变函数的上下文(this):

function greet() {
    console.log("Hello, " + this.name);
}

const person = {
    name: "LuQian"
};

greet.call(person); // 输出: Hello, LuQian
greet.apply(person); // 输出: Hello, LuQian

3.5 使用 bind

bind 方法创建一个函数,该函数在调用时会将 this 关键字指定为特定值:

function greet() {
    console.log("Hello, " + this.name);
}

const person = {
    name: "LuQian"
};

const greetLuQian = greet.bind(person);
greetLuQian(); // 输出: Hello, LuQian

3.6 箭头函数

箭头函数也是一种定义函数的方式,但它的 this 值在定义时决定,不会发生变化:

const person = {
    name: "LuQian",
    greet: () => {
        console.log("Hello, " + this.name); // this 指向外部上下文
    }
};

person.greet(); // 输出: Hello, undefined

箭头函数不绑定自己的 this,而是继承外部上下文的 this。在这个例子中,this 指向的是 greet 方法被调用时的上下文,而不是 person 对象,因此 this.name 返回 undefined

要解决这个问题,可以使用普通函数来定义 greet 方法,这样 this 就会指向调用该方法的对象 person。您可以将代码修改如下:

const person = {
    name: "LuQian",
    greet: function() { // 使用普通函数
        console.log("Hello, " + this.name); // this 指向 person 对象
    }
};

person.greet(); // 输出: Hello, LuQian

3.7 IIFE(立即调用的函数表达式)

一种在定义时立即执行函数的方法:

(function() {
    console.log("This function runs immediately!");
})(); // 输出: This function runs immediately!

 

4. 函数的返回值

在 JavaScript 中,函数的返回值是通过 return 语句返回的。一个函数可以返回任意类型的值,包括基本类型(如数字、字符串、布尔值等)和复杂类型(如对象、数组、函数等)。如果没有使用 return 语句,或者在函数执行完时未遇到 return,则函数默认返回 undefined

 

4.1 返回数字

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

const sum = add(2, 3); // sum 的值是 5

 

4.2 返回字符串

function greet(name) {
    return "Hello, " + name + "!";
}

const message = greet("Alice"); // message 的值是 "Hello, Alice!"

 

4.3 返回布尔值

function isEven(num) {
    return num % 2 === 0;
}

const result = isEven(4); // result 的值是 true

 

4.4 返回对象

function createPerson(name, age) {
    return {
        name: name,
        age: age
    };
}

const person = createPerson("Bob", 25); // person 的值是 { name: "Bob", age: 25 }

 

4.5 没有返回值

function logMessage(message) {
    console.log(message);
    // 没有 return 语句,默认返回 undefined
}

const result = logMessage("Hello!"); // result 的值是 undefined
函数返回值总结
使用 return 关键字来返回值。
函数可以返回任何类型的值,包括对象和数组。
如果没有 return 语句,函数会返回 undefined

5 函数参数

5.1 形参和实参

  • 形参(Formal Parameters):在函数定义中声明的变量,起到占位符的作用。函数在调用时,用实参给这些形参赋值。

    function foo(x, y) {
        return x + y;
    }
    
  • 实参(Actual Parameters):在函数调用时传递给函数的值。可以是字面量、变量、表达式、对象等。

    let result = foo(5, 10); // 5 和 10 是实参
    

 

5.2 默认参数

默认参数允许为函数参数提供默认值。可以在函数参数中直接指定默认值,如果调用时没有传递该参数,则使用默认值。

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

greet();          // 输出:Hello, Guest!
greet("LuQian");  // 输出:Hello, LuQian!

5.3 剩余参数

剩余参数 (...args) 可以收集函数调用时传入的多余参数,并将这些参数作为数组处理。这在处理不定数量的参数时非常有效。

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

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

5.4 参数解构

解构赋值允许我们从数组对象中提取值,并将其赋值给变量,在函数参数中也可以使用这种语法。

5.4.1 对象解构
function displayUser({ name, age }) {
    console.log(`Name: ${name}, Age: ${age}`);
}

const user = { name: "Bob", age: 30 };
displayUser(user); // 输出:Name: Bob, Age: 30

5.4.2 数组解构
function printCoordinates([x, y]) {
    console.log(`X: ${x}, Y: ${y}`);
}

const coordinates = [10, 20];
printCoordinates(coordinates); // 输出:X: 10, Y: 20

5.5 参数顺序和数量

JavaScript 函数可以接受比定义的形参数量更多或更少的实参:

  • 多余的实参会被忽略,只会使用形参列表中定义的前几个参数。
  • 缺少的实参将被赋值为 undefined

例子:

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

console.log(multiply(2, 3));     // 输出:6
console.log(multiply(2));        // 输出:NaN,因为 b 是 undefined
console.log(multiply(2, 3, 4));  // 输出:6, 4 被忽略

5.6 参数类型检查

JavaScript 是动态类型语言,参数类型是在运行时确定的。如果需要在函数中确保参数是特定类型,可以手动检查类型:

function addNumbers(x, y) {
    if (typeof x !== "number" || typeof y !== "number") {
        throw new Error("Both arguments must be numbers");
    }
    return x + y;
}

console.log(addNumbers(5, 10));     // 输出:15
// console.log(addNumbers(5, "10")); // 抛出错误

5.7 回调函数

在某些情况下,函数参数可以是另一个函数,即回调函数。这种方式让函数具有更好的灵活性和可扩展性。

function processUserInput(callback) {
    const userInput = "Hello, World!";
    callback(userInput);
}

//函数调用
processUserInput(function(input) {
    console.log(input);
}); // 输出:Hello, World!

5.8 箭头函数与常规函数的参数

箭头函数与常规函数相同,也可以接受参数,但其语法更为简洁。例如:

const add = (a, b) => a + b;
console.log(add(5, 3)); // 输出:8

5.9 最优参数待补充

在某些情况下,我们可能需要为参数设置最优值,这可以通过逻辑运算符实现:

			function multiply(a, b) {
				// 只在 b 为 undefined 时设为默认值 1
				b = (typeof b !== 'undefined') ? b : 1;
				return a * b;
			}

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

 

6. 函数参数的传递

在 JavaScript 中,函数参数的传递是通过“值传递”或“引用传递”进行的,这取决于参数的类型。

原始数据类型值传递,函数内修改不会影响外部变量。
对象类型引用传递,函数内修改会影响外部对象。

6.1 值传递

对于原始数据类型(如 numberstringbooleannullundefined 和 symbol),参数是按值传递的。这意味着在函数内部对参数的修改不会影响函数外部的变量。

示例:

function modifyValue(x) {
    x = 10;
    console.log("函数内部的值:", x); // 输出: 函数内部的值: 10
}

let a = 5;
modifyValue(a);
console.log("函数外部的值:", a); // 输出: 函数外部的值: 5

6.2 引用传递

对于对象类型(如数组、对象和函数),参数是按引用传递的。这意味着在函数内部对参数的修改会影响函数外部引用的对象。

示例:

function modifyObject(obj) {
    obj.name = "LuQian";
    console.log("函数内部的对象:", obj); // 输出: 函数内部的对象: { name: "LuQian" }
}

let person = { name: "Bob" };
modifyObject(person);
console.log("函数外部的对象:", person); // 输出: 函数外部的对象: { name: "LuQian" }

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

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

相关文章

温州大麓青年音乐节即将开唱,37组音乐人国庆齐聚共谱华章

金秋十月,当丰收的季节与音乐的旋律相遇,温州将迎来一场前所未有的文化盛事。2024年10月1日至4日,温州大麓青年音乐节将在瓯海盛大举行。不仅是一场音乐的狂欢,更是一次多元文化的碰撞与融合。本届音乐节邀请了37组以上的知名音乐…

WEB3.0是什么?

WEB3.0是什么? web3 之前用户创作分享内容,内容信息用户信息被运营平台的科技公司控制,比如某云,某信,某音,用户对直接的数据没有真正的所有权,web2平台拥有绝对控制权,想禁用你的账…

为什么说3-8岁的行为塑造奠定孩子的一生?

亲爱的爸爸妈妈: 育儿征程中会有无数问题在脑海中闪烁。孩子成长的每一步,都紧紧牵动着我们的心弦。 实际上,成长的关键在于塑造孩子五个至关重要的能力,分别是专注力、思维力、沟通力、抗逆力和行动力。 数业智能心大陆基于自研 …

CJEval:一个基于中国初中考试的多样化考试问题数据集

2024-09-26,由腾讯YouTu Lab和北京大学联合发布的CJEval,是一个基于中国初中生考试数据的评估基准,用于测试和分析大型语言模型(LLMs)在教育任务中的表现,从而提高在线教育平台的智能化水平。 一、背景&…

(done) 声音信号处理基础知识(11) (Complex Numbers for Audio Signal Processing)

参考:https://www.youtube.com/watch?vDgF4m0AWCgA&t1047s 似乎是因为信号处理需要使用复数,作者花了一节课介绍复数 据油管主所说,声学信号处理中引入复数的原因是:快速完成部分计算 这里的例子是,当我们做傅里…

Python库matplotlib之一

Python库matplotlib之一 plot函数使用列表或数组画线绘图的格式 matplotlib.pyplot 是使 matplotlib 像 MATLAB 一样工作的函数集合。每个 pyplot 函数都会对图形进行一些更改:例如, 创建图形在图形中创建绘图区域在绘图区域中绘制一些线条用标签装饰绘…

Redis --- 第一讲 --- 分布式简单介绍

一、认识Redis 定义变量,不就是在内存中存储数据吗?Redis是在分布式系统中,才能发挥威力的。如果只是单机程序。直接通过变量存储数据的方式势必使用Redis更优的选择。由于进程的的隔离性。进程之间通过网络通信,就能共享数据。Re…

keepalived+nginx实现高可用的案例详解(主主模式)

文章目录 前言keepalived主备模式和主主模式有什么区别1. 主备模式(Master-Backup Mode)2. 主主模式(Active-Active Mode 或 Dual Master Mode)主备模式 vs 主主模式 的区别总结: 环境案例实现具体步骤ngx1ngx2验证 前…

【教学类-56-05】数感训练——数字05(指定数字出现次数,速度快)

背景需求: 昨天有客户订购“阿拉伯数字的数感训练” 我查看文件夹,发现前期没有生成过0-50的数字(只研究了学号数感训练的学具) 赶紧用之前写过的代码生成了一份 【教学类-56-01】数感训练——数字01(同样的数字涂色…

猫头虎分享已解决Bug:npm warn old lockfile Could not fetch metadata for yallist@3.1.1

🐯猫头虎分享已解决Bug:npm warn old lockfile Could not fetch metadata for yallist3.1.1 今天有粉丝问猫哥:“🐯猫头虎,我在使用 npm 安装依赖时遇到了一个错误提示 Could not fetch metadata for yallist3.1.1&am…

凿岩机械液压比例多路阀控制器

工程机械应用的BEUEC比例放大器控制比例多路阀主要应用于以下几大类设备中: 1. 挖掘机械:包括挖掘机、挖掘装载机、挖掘船等,主要用于挖掘土壤、煤和矿石等物料。 2. 铲土运输机械:如推土机、铲运机、装载机等,主要用…

亚马逊测评,容易掉评是什么原因,怎么解决

大家好,今天来深入探讨如何有效提升亚马逊测评中的留评率,并解析那些导致评论掉落或难以留下的常见原因,以便采取针对性的策略来优化这一过程。作为卖家,提升留评率无疑是提升产品曝光度和销量的关键一环。 亚马逊测评掉评与留评…

【机器学习】目标分类算法概述

🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 ​💫个人格言: "如无必要,勿增实体" 文章目录 目标分类算法概述传统机器学习方法支持向量机(SVM)决策树和随机森林特征提取 基…

docker_阿里云镜像仓库

1.创建个人实例 登录阿里云——控制台——容器镜像服务——创建个人版实例 2.设置密码 设置后可在终端复制上图2测试 [rootserver ~]# sudo docker login --usernameyou_aliyun_name crpi-8y14tvgewmc6tisz.cn-hangzhou.personal.cr.aliyuncs.com Password: WARNING! Your …

Linux环境下安装python

Linux 环境下安装python 以下是在Linux环境下安装Python - 3.9.4.tgz的详细步骤:1. 下载Python - 3.9.4.tgz(如果未下载)2.解压文件3.安装依赖项(如果需要)4.配置和编译5.安装6.创建一个别名(alias&#xf…

中国车主,撑起天猫又一个万亿赛道

"今年双十一,预计会有超过1亿消费者来淘宝天猫汽车类目消费。3~5年之后,天猫汽车有望冲刺为阿里继大服饰、大快消、家装家电等之后又一个GMV(商品成交总额)破万亿的品类。" 淘天集团汽车事业部总经理、天猫养车总裁无封…

UART配置流程

S3C2440A 的通用异步收发器(UART)配有3 个独立异步串行I/O(SIO)端口,每个都可以是基于中断或基于DMA 模式的操作。换句话说,UART 可以通过产生中断或DMA 请求来进行CPU 和UART 之间的数据传输。UART 通过使…

网络安全 DVWA通关指南 DVWA Weak Session IDs(弱会话)

DVWA Weak Session IDs(弱会话) 文章目录 DVWA Weak Session IDs(弱会话)Low LevelMedium LevelHigh LevelImpossible Level 参考文献 WEB 安全靶场通关指南 相关阅读 Brute Force (爆破) Command Injection(命令注入…

Kafka学习笔记(一)Kafka基准测试、幂等性和事务、Java编程操作Kafka

文章目录 前言4 Kafka基准测试4.1 基于1个分区1个副本的基准测试4.2 基于3个分区1个副本的基准测试4.3 基于1个分区3个副本的基准测试5 Java编程操作Kafka5.1 引入依赖5.2 向Kafka发送消息5.3 从Kafka消费消息5.4 异步使用带有回调函数的生产消息6 幂等性6.1 幂等性介绍6.2 Kaf…

【linux】linux中如何通过Logstash处理、结合logrotate分割日志

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…