深入理解函数【JavaScript】

在 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 时设为默认值 1b = (typeof b !== 'undefined') ? b : 1;return a * b;}console.log(multiply(5)); // 输出:5console.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.xdnf.cn/news/1547637.html

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

相关文章

C# 委托(Delegate)一

一.Delegate的定义说明: C# 中的委托(Delegate)就是类似于 C 或 C 中函数的指针。Delegate 是存有对某个方法引用的一种引用类型变量,引用可在运行时是可以被改变的,特别适用于实现事件和回调方法。所有的Delegate都是…

C# 委托(Delegate)二

一.委托的多播(Multicasting of a Delegate): 委托对象,使用 "" 运算符进行合并,一个合并委托调用它所合并的两个委托。使用"-" 运算符从合并的委托中移除组件委托。 注:只有相同类型…

linux文件下载分类

在下载图片时各个网站命名不统一,管理起来很麻烦,想要写一个脚本将下载的图片或者其他资源实现格式统一,方便管理 $0:表示脚本路径。运行 ./myscript.sh,$0 将会保存 ./myscript.sh。 $1:表示传递给脚本的…

Leetcode 968. 监控二叉树 树形dp、状态机 C++实现

问题:Leetcode 968. 监控二叉树 给定一个二叉树,我们在树的节点上安装摄像头。 节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。 计算监控树的所有节点所需的最小摄像头数量。 /*** Definition for a binary tree node.* struct TreeNo…

数据结构 ——— 移除元素(快慢指针)

目录 题目要求 代码实现(快慢指针) 题目要求 编写函数,给你一个数组 nums 和一个值 val,你需要在 nums 数组 原地 移除所有数值等于 val 的元素,并且返回移除后数组的新长度 不能使用额外的数组空间,要…

数据统计与分析-Numpy入门

Numpy入门 导包1.演示Numpy的属性演示打印Numpy数据类型shape()形状维度ndim() 轴dtype() 元素类型size()元素个数itemsize()每个匀速所占大小 2.创建Numpy对象2.1数组方式创建,函数:arrray()2.2创建空的ndarray对象2.2.1 zeros()2.2.2 ones()2.2.3 empty() 2.3创建1个指定范围…

大数据毕业设计选题推荐-内蒙古旅游景点数据分析系统-Hive-Hadoop-Spark

✨作者主页:IT研究室✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

【智能控制】16章 基于Hopfield网络的路径优化,TSP问题

目录 15.6 基于Hopfield网络的路径优化 15.6.1 TSP问题 15.6.2 求解TSP问题的Hopfield神经网络设计 15.6 基于Hopfield网络的路径优化 15.6.1 TSP问题 旅行商问题(Traveling Salesman Problem,简称TSP)可描述为:已知N个城市之…

C# 的枚举(Enum)应用说明

一.Enum的定义&#xff1a; 枚举是一组命名整型的常量。枚举类型是使用 enum 关键字声明的&#xff0c;它是值类型。枚举包含自己的值&#xff0c;且不能继承或传递继承。 二.声明 enum 变量&#xff1a; 声明枚举的一般语法&#xff1a; enum <enum_name> { enumerati…

如何使用ssm实现基于BS的库存管理软件设计与实现+vue

TOC ssm708基于BS的库存管理软件设计与实现vue 绪论 课题背景 身处网络时代&#xff0c;随着网络系统体系发展的不断成熟和完善&#xff0c;人们的生活也随之发生了很大的变化。目前&#xff0c;人们在追求较高物质生活的同时&#xff0c;也在想着如何使自身的精神内涵得到…

FPGA学习(1)-mux2,2选1多路器

目录 1 开发板配套资料 1.1学习网址和资料网址 2.创建工程文件 2.1创建过程 2.2写程序及仿真测试 2.2.1 写程序生成电路 2.2.2仿真 2.2.3 生成执行文件并烧录 3.实验现象 买的小梅哥店铺的开发板&#xff1a;xc7z020clg400 看的小梅哥的视频&#xff1a;03C _基于ZYN…

Oracle 相关的工具使用 SQL Developer , sqlplus

Oracle 相关的工具使用 SQL Developer &#xff0c; sqlplus 一&#xff0c;Oracle SQL Developer 连接数据库 今天在连接sqldeveloper服务器时遇到了很多问题&#xff0c;但最终还是通过网上的博客解决了问题&#xff0c;我就在总结一下我的解决过程。 一.界面 首先&#…

混拨动态IP代理的优势是什么

在当今互联网时代&#xff0c;隐私保护和网络安全成为了人们关注的焦点。无论是个人用户还是企业&#xff0c;都希望能够在网络上自由、安全地进行各种活动。混拨动态IP代理作为一种新兴的技术手段&#xff0c;正逐渐受到大家的青睐。那么&#xff0c;混拨动态IP代理到底有哪些…

c语言常量变量

c语言常量变量 const 修饰常变量 #define定义标识符常量 #define num 10 //这里不需要分号int anum;enum枚举常量 enum Color {RED,GREEN,BLUE }; int main(){enum Color cRED;//枚举常量不允许修改 }//定义常量 int a10; char ba;错误语法注意 //定义常变量 const int a10…

windows 桌面采集音频

头文件&#xff1a; #ifndef __CAPTURE_AUDIO__ #define __CAPTURE_AUDIO__#include <functional> #include <windows.h> #pragma comment(lib, "winmm.lib")class CaptureAudio { public:CaptureAudio();~CaptureAudio();public:bool Init(const std::…

JSON与CSV之间的主要区别

今天要和大家深入探讨一个数据处理中的常见问题——JSON与CSV之间的主要区别。这两种数据格式各有千秋&#xff0c;适用于不同的场景。让我们一起来了解它们的特点和应用。 一、数据结构的差异 首先&#xff0c;JSON是一种轻量级的数据交换格式&#xff0c;能够表示复杂的数据…

Unity开发绘画板——04.笔刷大小调节

笔刷大小调节 上面的代码中其实我们已经提供了笔刷大小的字段&#xff0c;即brushSize&#xff0c;现在只需要将该字段和界面中的Slider绑定即可&#xff0c;Slider值的范围我们设置为1~20 代码中只需要做如下改动&#xff1a; public Slider brushSizeSlider; //控制笔刷大…

深圳易图讯科技场区态势感知系统

一、功能与目标优化描述&#xff1a; .图像采集、传输、存储与管理系统&#xff1a; 实时采集&#xff1a;利用摄像头、移动摄像设备及微距摄像头&#xff0c;全面覆盖场区内固定点位和重要场地&#xff0c;实现视频图像的实时采集。 高效传输&#xff1a;通过有线、无线网…

秒懂Linux之信号

目录 信号的基本概念 信号的处理方式 默认动作 自定义处理信号 忽略该信号 信号的产生方式 kill命令 键盘组合键 系统调用 软件条件 异常 信号产生的深层理解 core的功能 信号的阻塞 内核中的表示 sigset_t 信号集操作函数 sigprocmask sigpending …

关于最小二乘法

最小二乘法的核心思想简单而优雅&#xff1a;我们希望找到一条最佳的曲线&#xff0c;使其尽可能贴近所有的数据点。想象一下&#xff0c;当你在画布上描绘一条线&#xff0c;目标是让这条线与点的距离最小。数学上&#xff0c;这可以表示为&#xff1a; 在这个公式中&#xff…