【JavaScript速成之路】JavaScript函数
📃个人主页:「小杨」的csdn博客
🔥系列专栏:【JavaScript速成之路】
🐳希望大家多多支持🥰一起进步呀!
文章目录
- 前言
- 1,函数基础
- 1.1,函数概念
- 1.2,函数使用
- 1.3,函数参数
- 1.4,函数返回值
- 2,函数进阶
- 2.1,函数表达式
- 2.2,回调函数
- 2.3,递归函数
- 3,作用域
- 3.1,作用域分类
- 3.2,变量分类
- 3.3,作用域链
- 4,闭包函数
- 5,预解析
- 结语
前言
📜前言:小杨在上一篇带着大家一起学习了JavaScript中的数组,想必大家对JavaScript的数组知识已经有所了解了,那么今天我们将继续带着大家学习一下JavaScript中的函数的相关知识,希望大家收获多多!
1,函数基础
1.1,函数概念
函数就是封装了一段可以被重复执行调用的代码块。
函数引入的目的就是为了解决代码的重复问题,让代码重复使用。
1.2,函数使用
函数使用可分为两步,即声明函数和调用函数两部分。
1,声明函数语法:
function 函数名(参数列表){//函数体
}
知识点:
- function是声明函数的关键字,必须全部小写。
- 函数是完成某一功能的代码,故函数名一般为动词。
- 函数不能自己调用自己。
2,调用函数语法:
函数名();
知识点:
- 调用函数的时候千万不要忘记添加小括号。
- 声明函数本身并不会执行代码,只有调用函数时才会执行函数体代码。
- 口诀:代码不调用,自己不执行。
3,函数封装
函数具有封装代码的效果,也就是把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口。
封装思想类似于将计算机内部的主板,CPU中央处理器,内存等硬件全部安装到机箱里,对外只提供一些像电源接口,显示接口,USB接口这样简单的接口给用户使用。
1.3,函数参数
在函数内部的代码中,当某些值不能确定时,可以通过函数的参数从外部接收,一个函数可以通过传入不同的参数来完成不同的操作。
1,参数分类
函数参数分为形参和实参两种。
-
形参是指在声明函数时,函数名后面的小括号里添加的一些参数。
-
实参是指在调用函数时,传递给函数的对应形参的一些参数。
为了更加直观的辨别形参和实参,示例如下:
function 函数名(形参1,形参2,形参3....){ //函数声明的小括号里面的参数//函数体代码
}
函数名(实参1,实参2,实参3....); //函数调用的小括号里面的参数
知识点:
-
函数的形参是形式上的参数,因为当函数声明时,这个函数还没有被调用,这些形参具体传入值是不确定的。
-
函数的实参则是实际上的参数,因为在函数调用时,这些形参的值就会被确定下来,传递给与之对应的形参。
2,参数数量
JavaScript函数参数的使用比较灵活,允许函数的形参和实参个数不同。
- 实参的个数等于形参的个数时,函数正常执行。
- 实参的个数多于形参的个数时,函数也可正常执行,多余的实参因无形参接收会被忽略。
- 实参的个数少于形参的个数时,函数也可正常执行,多余的形参类似于一个已声明但未赋值的变量,其值为undefined。
为了更好地理解上述语法,示例如下:
<script>function getNums(num1,num2){console.log(num1,num2);}getNums(1); //实参个数少于形参个数getNums(1,2); //实参个数等于形参个数getNums(1,2,3); //实参个数多于形参个数
</script>
示例结果:
3,arguments
当我们不确定有多少个参数传递的时候,我们就可以使用arguments来获取。
在JavaScript中,arguments这个是啥?arguments实际上是当前函数的一个内置函数。
所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有参数。
arguments展示形式是一个伪数组,因此可以像数组一样进行遍历。
那数组与伪数组有啥区别呢?伪数组具有以下特性:
- 具有数组的length属性
- 按索引方式进行存储数据
- 不具有数组的push,pop等方法
为了更好地理解arguments的使用,示例如下:
<script>function fn(){ console.log(arguments); //arguments里存储所有传递过来的参数console.log(arguments.length); //arguments具有数组的length属性console.log(arguments[0]); //arguments按索引方式进行存储数据}fn(1,2,3,4);
</script>
示例结果:
1.4,函数返回值
当函数完成了函数代码块的基本功能后,需要通过函数的返回值来将函数的处理结果返回。
函数返回值是通过return语句来实现的,语法格式:
function 函数名(){return 要返回的值;
}
函数返回值使用有以下两种方式:
1,通过变量接收返回值
var result = 函数名();
console.log(result);
2,直接输出函数返回值
console.log(函数名());
知识点:若函数没有使用return返回一个值,则函数调用后获取的返回结果为undefined。
为了更好地理解函数返回值的语法,示例如下:
<script>function getResult(){return 121;}var result = getResult();console.log(result);console.log(getResult());
</script>
示例结果:
2,函数进阶
2.1,函数表达式
函数表达式是将声明的函数赋值给一个变量,通过变量完成函数的调用和参数的传递。
为了更好理解函数表达式,示例如下:
<script>var sum = function(num1,num2){ //函数表达式return num1 + num2;}; console.log(sum(13,14)); //调用函数
</script>
示例结果:
知识点:
- 函数表达式与函数声明的定义方式几乎相同,不同的是函数表达式的定义必须在函数调用之前,而函数声明的方式则不限制声明与调用顺序。
2.2,回调函数
回调函数指的是一个函数A作为参数传递给一个函数B,然后在函数B的函数体内调用函数A,此时函数A被称为回调函数。
其中,匿名函数常用作函数的参数传递,从而实现回调函数。
为了更好理解何为回调函数及使用,示例如下:
<script>function fn1(num1,num2,fn){return fn(num1,num2);}console.log(fn1(45,55,function(a,b){return a + b;}));
</script>
示例结果:
知识点:
- 在函数中设置了回调函数后,可以根据调用时传递的不同参数(相加的函数,相乘的函数等),在函数体中特定的位置实现不同的功能,相当于在函数体内根据用户的需求来完成了不同功能的定制。
2.3,递归函数
函数的递归指的是一个函数在其函数体内调用自身的过程。需要特别注意的是 ,函数递归只可在特定的情况下使用。
为了更好地理解何为递归函数及使用,示例如下:
<script>
function fun(n){if(n == 1){return 1;}return n * fun(n - 1);
}
var ret = fun(5);
console.log(ret);
</script>
示例结果:
示例说明:上述代码定义了一个递归函数fun()用于实现n的阶乘计算,当n不等于1时,递归当前变量n乘以fun(n-1),直到n等于1时,返回1。
注意:递归调用虽然在遍历维数不固定的多维数组时非常适合,但它占用的内存和资源比较多,同时难以实现和维护,因此在开发中需谨慎使用。
3,作用域
3.1,作用域分类
一般来说,一段代码中所用到的变量名或函数名并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
作用域的目的就是为了有效减少命名冲突的情况。变量需要先声明后使用,但不意味着声明变量后就可以在任意位置使用该变量。
例如,在函数声明一个age变量,在函数外进行访问,就会出现age变量未定义的错误。
<script>function fun(){var age = 19;}console.log(age);
</script>
示例结果:
从上述代码可以知道,变量需要在它的作用域范围内才可以被使用,这个作用域被称为变量的作用域。
JavaScript根据作用域使用范围的不同,将其划分为全局作用域,函数作用域和块级作用域(ES6提供的)。
- 全局作用域是整个script标签 或者 一个单独的JavaScript文件。
- 局部作用域也称函数作用域,在函数内部就是函数作用域,这个代码名字只能在函数内部起效果和作用。
为了更好理解上述语法,示例如下:
<script>//全局作用域var num = 20; //全局变量function fun(){//局部作用域var num = 10; //局部变量console.log(num); //输出局部变量值:10}fun();console.log(num); //输出全局变量值:20
</script>
3.2,变量分类
在JavaScript中,对不同的作用域内声明的变量进行划分,可划分为全局变量,局部变量,块级变量三类。
- 全局变量:不在任何函数内声明的变量(显式定义)或在函数内省略var声明的变量隐式定义)都称为全局变量,它在同一个页面文件中的所有脚本内都可以使用。
- 局部变量:在函数体内利用var关键字定义的变量称为局部变量,它仅在该函数体内有效。
- 块级变量:ES6提供的let关键字声明的变量称为块级变量,仅在“0”中间有效,如if、for或while语句等。
知识点:
- 当全局变量名和局部变量名相同时,两者的使用互不影响。
- 局部变量只能在函数内部使用,函数的形参也属于局部变量。
- 函数中的变量如果省略var关键字,它会自动向上级作用域查找变量,一直找到全局作用域为止。
<script>function fn(){num = 10;}fn();console.log(num);
</script>
-
在全局作用域下,添加或者省略var关键字都可以声明全局变量。而在函数中,添加var关键字声明的变量是局部变量,省略var关键字时,如果变量在当前作用域不存在,会自动向上级作用域查找变量。
-
从执行效率来说,全局变量在浏览器关闭页面的时候才会销毁,比较占用内存资源;而局部变量在函数执行完成后就会被销毁,比较节约内存资源。
3.3,作用域链
当在一个函数内部声明另外一个函数时,就会出现函数嵌套的效果。当函数嵌套时,内层函数只能在外部函数作用域内执行,在内层函数执行过程中,若需要引入某个变量,首先会在当前作用域中寻找,若未找到,则继续向上一层级的作用域中寻找,直到全局作用域。
简而言之,作用域链是指内部函数访问外部函数的变量,采取的是链式查找的方式来决定那个值。
为了更好理解上述作用域链的语法,示例如下:
<script>var num = 10;function fn(){ //外部函数var num = 20;function fun(){ //内部函数console.log(num); //输出num值:20 } //口诀:就近原则fun();}fn();
</script>
示例结果:
4,闭包函数
在JavaScript中,内嵌函数可以访问定义在外层函数中的所有的变量和函数,并包括其外层函数能访问的所有变量和函数。
但是在函数外部则不能访问函数的内部变量和嵌套函数,此时可通过使用闭包来实现。
**那闭包是啥东东呢?**闭包指的就是有权访问另一函数作用域内变量(局部变量)的函数。
那闭包有啥用呢? 闭包的用途可归纳为以下两种:
- 可以在函数外部读取函数内部的变量。
- 可以让变量的值始终在内存中。
知识点1:由于闭包会使得函数中的变量一直被保存在内存中,内存消耗很大,所以滥用闭包可能会降低程序的处理速度,造成内存消耗等问题
知识点2:常见的闭包创建的方式就是在一个函数内部创建另外一个函数,通过另外一个函数访问这个函数的局部变量。
为了更好地理解该知识点,示例如下:
<script>function fun(){var num = 0;var a = function(){return ++num;};return a;}//保存fun返回的函数,此时ret就是一个闭包var ret = fun(); //访问测试console.log(ret());console.log(ret());console.log(ret());console.log(ret());console.log(ret());
</script>
示例结果:
5,预解析
JavaScript代码由浏览器中的JavaScript解析器来执行的,JavaScript解析器在运行JavaScript代码时会进行预解析。
**那该如何理解预解析呢?**预解析就是提前将代码中的var变量声明和function函数声明进行解析,然后再去执行其它的代码。
JavaScript引擎运行JavaScript分为两步:预解析和代码执行。
预解析分为变量预解析(变量提升)和函数预解析(函数提升)两类。
- 变量提升就是将所有的变量声明提升到当前作用域的最前面,但不提升赋值操作。
- 函数提升就是将所有的函数声明提升到当前作用域的最前面,但不调用函数。
为了更好理解预解析的使用,示例如下:
预解析示例1:
<script>function fn(){var num2 = 456;console.log(num1);console.log(num2);var num1 = 123;}fn();
</script>
上述代码经过预解析的处理后:
<script>function fn(){var num2;var num1;num2 = 456;console.log(num1);console.log(num2);num1 = 123;}fn();
</script>
预解析示例1结果:
预解析示例2:
<script>fn1();console.log(c);console.log(b);console.log(a);function fn1(){var a = b = c = 9;console.log(a);console.log(b);console.log(c);}
</script>
上述代码经过预解析的处理后:
<script>function fn1(){var a;a = 9;b = 9;c = 9; //b和c为全局变量,a为局部变量console.log(a);console.log(b);console.log(c);}fn1();console.log(c);console.log(b);console.log(a);</script>
预解析示例2结果:
结语
这就是本期博客的全部内容啦,想必大家已经对JavaScript中函数的相关内容有了全新地认识和理解吧,如果有什么其他的问题无法自己解决,可以在评论区留言哦!
最后,如果你觉得这篇文章写的还不错的话或者有所收获的话,麻烦小伙伴们动动你们的小手,给个三连呗(点赞👍,评论✍,收藏📖),多多支持一下!各位的支持是我最大的动力,后期不断更新优质的内容来帮助大家,一起进步。那我们下期见!
相关文章:

【JavaScript速成之路】JavaScript函数
📃个人主页:「小杨」的csdn博客 🔥系列专栏:【JavaScript速成之路】 🐳希望大家多多支持🥰一起进步呀! 文章目录前言1,函数基础1.1,函数概念1.2,函数使用1.3&…...

萤火虫算法优化SVM变压器故障分类预测,fa-svm分类预测,libsvm参数优化
目录 支持向量机SVM的详细原理 SVM的定义 SVM理论 Libsvm工具箱详解 简介 参数说明 易错及常见问题 SVM应用实例,基于fa-svm分类预测 代码 结果分析 展望 支持向量机SVM的详细原理 SVM的定义 支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是…...

JavaScript DOM API的使用
文章目录一. 什么是DOM二. 最常用的DOM API1. 选中页面元素2. 操作元素的属性2.1 事件概念2.2 获取/修改元素内容计数器2.4 获取/修改元素属性点击图片切换2.5 获取/修改表单元素属性表单计数器全选/取消全选按钮2.6 获取修改样式属性点击文字放大实现夜间/日间模式的切换3. 操…...

Vue组件库出现$listeners is readonly等错误的原因及预防方法
本文主要是面向写组件库的人士,而不是组件库的使用人士。 出现原因 根本原因是因为组件库的package.json中 dependencies包含了vue包,然后导致最后打包出来的组件库也包含vue包 然后和引用这个组件库的项目中的vue发生冲突。 举个例子,pro…...

lsusb
用法: lsusb -hUsage: lsusb [options]... List USB devices -v, --verbose Increase verbosity (show descriptors) -s [[bus]:][devnum] Show only devices with specified device and/or bus numbers (in decimal) -d vendor:[product] …...

Allegro如何在PCB中添加层面操作指导
Allegro如何在PCB中添加层面操作指导 在用Allegro做PCB设计的时候,根据需要,会在PCB中额外添加一些额外的层面,如下图 如何添加,具体操作如下 点击Setup点击Subclasses...

淘宝widget链路方案总结
目前widget生态已经做了大量的基建工作,同时在widget生态的演进过程中我们发现如何匹配用户的偏好一直以来是一个挑战工作,本文介绍了widget的整体链路。业务背景▐ widget介绍2020年底iOS推出了新版widget之后引起了一些声浪,但仍然很多苹果用户并不了…...

c++指针
内存地址 将内存抽象成一个很大的一维字符数组,编码就是对内存的每一个字节分配一个32位或64位的二进制编号。这个内存编号称之为内存地址(唯一),内存中的每一个数据都会分配相应的地址。 #include<iostream> using namesp…...

Qt 贴图实现方向控制盘
一、效果走一波 二、使用贴图进行不规则按钮的设计与开发 开发环境描述:QtCreator Qt Desinger (1)首先准备待贴的图片 图片的切片大小必须一样,背景为透明的;将待贴的所有图片都切下来,文件标明名称…...

建模杂谈系列211 ADBS的取数模式以及衔接
说明 这应该是进一步的完善ADBS的工作模式。 之所以做A系列的架构工具,就是为了可以实现大型的数据处理、存储。从应用上说,是为了提高效率,并达到超高的效果。 为了达到这个目的,就必须从数据架构上、任务调度上、逻辑架构上作…...

易基因:RRBS揭示晚年锻炼可以减缓骨骼肌表观遗传衰老(甲基化年龄)|新研究
大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。2021年12月21日,美国阿肯色大学、德克萨斯大学和肯塔基大学的研究人员合作在《Aging Cell》杂志发表了题为“Late-life exercise mitigates skeletal muscle epigenetic aging”…...

JVM的基本知识
JVM JVM是java的虚拟机,是一个十分复杂的东西,所以掌握的要求比较高.本文主要是研究JVM的三大话题 JVM内存划分JVM类加载JVM的垃圾回收 JVM内存划分 java程序要执行的时候,JVM会先申请一块空间,这里就涉及到JVM的内存划分 堆 : 放的是new 出来的对象栈: 放的是方法之间的调…...

STM32移植FreeRTOS操作系统
一、FreeRTOS源码下载(1)移植钱得准备前菜对吧,我们先来去官网瞄一瞄网址:https://freertos.org/zh-cn-cmn-s/ 第一步:点击下载FreeRTOS第二步:选择版本下载(我选择稳定版本)注&…...

【专项训练】泛型递归、树的递归
递归和循环没有明显的边界! 不要进行人肉递归! 找最近重复子问题,直接写递归! 数学归纳法思维:1,2,…… 70. 爬楼梯 https://leetcode.cn/problems/climbing-stairs/ 互斥,且加在一起是全部答案! 动态规划法:用数组做递推,就是动态规划!!! class Solution...

React18 setState是同步还是异步?
相信大家对于react的setState肯定是不陌生了, 这是一个用于更新状态的函数. 但是在之前有一道非常经典的面试题就是关于setState是同步还是异步的问题, 具体可以参考我之前写的一篇文章: 一篇文章彻底理解setState是同步还是异步!. 对于react 18之前的版本, 上文说的…...

Kafka消费者 TCP管理
Kafka消费者 TCP管理创建 TCPFindCoordinator连接协调者消费数据TCP 连接数关闭 TCP 连接消费者的程序入口类是 KafkaConsumer 构建 KafkaConsumer 时 ,不会创建任何 TCP 连接TCP 连接是用 KafkaConsumer.poll 创建 创建 TCP poll 创建 TCP 的地方 : 发起 FindC…...

软考高级备考哪一个类型好些?
软考高级是比中级和初级难,科目就要考三科,选择题基础知识简答题案例分析写作论文 软考高级科目有:信息系统项目管理师、系统分析师、系统架构设计师、网络规划师、系统规划与管理师。如下: 软考高级中高项信息系统项目管理师师比…...

2023 HBU 天梯赛第一次测试 题目集
目录 1 建校日期 2 发射小球 3 背上书包去旅行 4 吉利的数字 5 向前走 6 热水器 7 走方格 8 朋友圈 9 交保护费 10 走方格 11 和与积 12 缩短字符串 13 买木棒 1 建校日期 在2022 ICPC沈阳站上,东北大学命题组给参赛的选手们出了一道签到题࿰…...

华为OD机试题,用 Java 解【子序列长度】问题
华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典使用说明 参加华为od机试,一定要注意不…...

内网环境解决SSL证书问题
本来这个没什么好写的,但是坑实在有点多,不得不写个文章记录下来。 创建证书看这里!!! 很多知识点要结合这个页面内容来看。 创建证书已经看过相关文章,然后用unity跑的时候发现连不上,完全没…...

数据分析方法01对比分析法
对比分析法 1、概念 基于相同的数据标准下,把两个及以上相互联系的指标数据进行比较,准确量化的分析他们的差异,说明研究对象在规模大小,水平高低,速度快慢等的不同表现,目的是为了找到差异的原因&#x…...

基于SMOKE多模式排放清单处理技术及EDGAR/MEIC清单制作与VOCs排放量核算
查看原文>>>基于SMOKE多模式排放清单处理技术及EDGAR/MEIC清单制作与VOCs排放量核算 (qq.com)随着我国经济快速发展,我国面临着日益严重的大气污染问题。近年来,严重的大气污染问题已经明显影响国计民生,引起政府、学界和人们越来越…...

CSS流动布局-页面自适应
项目中经常会碰到页面自适应的问题,例如:商城的列表展示、分类列表展示等页面,如下: 该页面会随着页面的放大缩小而随之发生变化,这种自适应的页面布局在大屏幕、小屏幕、不同的浏览器设备上都应该呈现出与设计匹配的…...

3.Elasticsearch初步进阶
3.Elasticsearch初步进阶[toc]1.文档批量操作批量获取文档数据批量获取文档数据是通过_mget的API来实现的在URL中不指定index和type请求方式:GET请求地址:_mget功能说明:可以通过ID批量获取不同index和type的数据请求参数docs:文档数组参数_index:指定index_type:指定type_id:指…...

优思学院|六西格玛管理的核心理念是什么?
六西格玛管理是一种基于数据分析的质量管理方法,旨在通过降低过程的变异性来达到质量稳定和优化的目的。该方法以希腊字母“σ”为名,代表标准差,是衡量过程变异性的重要指标。 六西格玛管理的核心理念是“以客户为中心、以数据为基础、追求…...

第十七节 多态
多态 什么是多态? ●同类型的对象,执行同一个行为,会表现出不同的行为特征。 多态的常见形式 父类类型 对象名称new子类构造器; 接口 对象名称new 实现类构造器; 多态中成员访问特点 ●方法调用:编译看左边,运行看右边。 ●变量调用:编译看…...

[vue]提供一种网站底部备案号样式代码
演示 vue组件型(可直接用) 组件代码:copyright-icp.vue <template><div class"icp">{{© ${year} ${author} }}<a href"http://beian.miit.gov.cn/" target"_blank">{{ record }}</a…...

python第四天作业~函数练习
目录 作业4、判断以下哪些不能作为标识符 A、a B、¥a C、_12 D、$a12 E、false F、False 作业5: 输入数,判断这个数是否是质数(要求使用函数 for循环) 作业6:求50~150之间的质数是…...

linux安装influxdb-rpmyum方式
一、influxdb的安装InfluxDB简介时序数据库InfluxDB版是一款专门处理高写入和查询负载的时序数据库,用于存储大规模的时序数据并进行实时分析,包括来自DevOps监控、应用指标和IoT传感器上的数据主要特点:专为时间序列数据量身订造高性能数据存…...

死锁
1.死锁的定义 多线程以及多进程改善了系统资源的利用率并提高了系统 的处理能力。然而,并发执行也带来了新的问题——死锁。所谓死锁是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法…...