【JavaScript速成之路】JavaScript函数

news2024/11/18 13:38:59

在这里插入图片描述

📃个人主页:「小杨」的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>

示例结果:

image-20221011215342035


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>

示例结果:

image-20221011222857689


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>

示例结果:

image-20221011225043554


2,函数进阶

2.1,函数表达式

函数表达式是将声明的函数赋值给一个变量,通过变量完成函数的调用和参数的传递。

为了更好理解函数表达式,示例如下:

<script>
    var sum = function(num1,num2){   //函数表达式
        return num1 + num2;
    }; 
    console.log(sum(13,14));         //调用函数
</script>

示例结果:

image-20221011230855069

知识点:

  • 函数表达式与函数声明的定义方式几乎相同,不同的是函数表达式的定义必须在函数调用之前,而函数声明的方式则不限制声明与调用顺序。

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>

示例结果:

image-20221011232242150

知识点

  • 在函数中设置了回调函数后,可以根据调用时传递的不同参数(相加的函数,相乘的函数等),在函数体中特定的位置实现不同的功能,相当于在函数体内根据用户的需求来完成了不同功能的定制。

2.3,递归函数

函数的递归指的是一个函数在其函数体内调用自身的过程。需要特别注意的是 ,函数递归只可在特定的情况下使用。

为了更好地理解何为递归函数及使用,示例如下:

<script>
function fun(n){
    if(n == 1){
        return 1;
    }
    return n * fun(n - 1);
}
var ret = fun(5);
console.log(ret);
</script>

示例结果:

image-20221012230002831

示例说明:上述代码定义了一个递归函数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>

示例结果:

image-20221012232338424

从上述代码可以知道,变量需要在它的作用域范围内才可以被使用,这个作用域被称为变量的作用域。

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>

image-20221012235228371


  • 在全局作用域下,添加或者省略var关键字都可以声明全局变量。而在函数中,添加var关键字声明的变量是局部变量,省略var关键字时,如果变量在当前作用域不存在,会自动向上级作用域查找变量。

  • 从执行效率来说,全局变量在浏览器关闭页面的时候才会销毁,比较占用内存资源;而局部变量在函数执行完成后就会被销毁,比较节约内存资源。


3.3,作用域链

当在一个函数内部声明另外一个函数时,就会出现函数嵌套的效果。当函数嵌套时,内层函数只能在外部函数作用域内执行,在内层函数执行过程中,若需要引入某个变量,首先会在当前作用域中寻找,若未找到,则继续向上一层级的作用域中寻找,直到全局作用域。

简而言之,作用域链是指内部函数访问外部函数的变量,采取的是链式查找的方式来决定那个值。

为了更好理解上述作用域链的语法,示例如下:

<script>
    var num = 10;
    function fn(){              //外部函数
        var num = 20;
        function fun(){         //内部函数
            console.log(num);   //输出num值:20  
        }                       //口诀:就近原则
        fun();
    }
    fn();       
</script>

示例结果:

image-20221013000353011


4,闭包函数

在JavaScript中,内嵌函数可以访问定义在外层函数中的所有的变量和函数,并包括其外层函数能访问的所有变量和函数。

但是在函数外部则不能访问函数的内部变量和嵌套函数,此时可通过使用闭包来实现。

**那闭包是啥东东呢?**闭包指的就是有权访问另一函数作用域内变量(局部变量)的函数。

那闭包有啥用呢? 闭包的用途可归纳为以下两种:

  1. 可以在函数外部读取函数内部的变量。
  2. 可以让变量的值始终在内存中。

知识点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>

示例结果:

image-20221013001118521


5,预解析

JavaScript代码由浏览器中的JavaScript解析器来执行的,JavaScript解析器在运行JavaScript代码时会进行预解析。

**那该如何理解预解析呢?**预解析就是提前将代码中的var变量声明和function函数声明进行解析,然后再去执行其它的代码。

JavaScript引擎运行JavaScript分为两步:预解析和代码执行。

预解析分为变量预解析(变量提升)和函数预解析(函数提升)两类。

  1. 变量提升就是将所有的变量声明提升到当前作用域的最前面,但不提升赋值操作。
  2. 函数提升就是将所有的函数声明提升到当前作用域的最前面,但不调用函数。

为了更好理解预解析的使用,示例如下:

预解析示例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结果:

image-20221013002433782

预解析示例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结果:

image-20221013003120880



结语

这就是本期博客的全部内容啦,想必大家已经对JavaScript中函数的相关内容有了全新地认识和理解吧,如果有什么其他的问题无法自己解决,可以在评论区留言哦!

最后,如果你觉得这篇文章写的还不错的话或者有所收获的话,麻烦小伙伴们动动你们的小手,给个三连呗(点赞👍,评论✍,收藏📖),多多支持一下!各位的支持是我最大的动力,后期不断更新优质的内容来帮助大家,一起进步。那我们下期见!

在这里插入图片描述


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

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

相关文章

sHMIctrl 曲线控件使用

目录 效果 官方介绍 ​编辑 名词解释 使用方法 显示点 点在X轴位置 点在Y轴位置 量程 单位 如何设置自动标尺数据 设置量程 设置单位 效果 官方介绍 名词解释 四条曲线&#xff1a;同时最多使用4条曲线。 每条条曲线最多512点&#xff1a;X2-X1-Xn&#xff1b; 数据自定…

认识CSS值如何提高写前端代码的效率

&#x1f31f;所属专栏&#xff1a;前端只因变凤凰之路&#x1f414;作者简介&#xff1a;rchjr——五带信管菜只因一枚&#x1f62e;前言&#xff1a;该系列将持续更新前端的相关学习笔记&#xff0c;欢迎和我一样的小白订阅&#xff0c;一起学习共同进步~&#x1f449;文章简…

Spring注解开发之组件注册(一)

Spring注解开发 Spring注解开发之组件注册下半篇 IOC&#xff0c;中文名为控制反转&#xff0c;是将Java的bean对象存储在容器中&#xff0c;当需要使用时&#xff0c;通过名字获取该对象。而不是通过new关键字去创建。 1.Configuration & Bean给容器中注册组件 第一种&…

K_A16_003 基于STM32等单片机采集薄膜压力传感器参数串口与OLED0.96双显示

K_A16_003 基于STM32等单片机采集薄膜压力传感器参数串口与OLED0.96双显示一、资源说明二、基本参数参数引脚说明三、驱动说明对应程序:四、部分代码说明1、接线引脚定义STM32F103C8T6薄膜压力传感器模块五、基础知识学习与相关资料下载六、视频效果展示与程序资料获取七、注意…

Allegro如何在PCB中添加层面操作指导

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

实在智能RPA入选中国信通院《高质量数字化转型产品及服务全景图》

近日&#xff0c;中国信息通信研究院“高质量数字化转型创新发展大会暨中国信通院‘铸基计划’年度峰会”在北京召开&#xff0c;大会上信通院揭晓了《高质量数字化转型产品及服务全景图&#xff08;2022&#xff09;》&#xff08;以下称“全景图”&#xff09;。实在智能凭借…

自己定义typescript的类型声明文件xx.d.ts

****内容预警***菜鸟新手内容&#xff0c;大佬请绕道&#xff0c;不对的请指出我们在使用typescript的使用&#xff0c;如果安装一个包没有相应的类型声明文件&#xff0c;ts的类型检查就会报错&#xff0c;所以我们经常会安装npm包对应的types类型声明包&#xff0c;比如uuid …

手把手教你安装Linux!!!

文章目录Linux简述它们的区别安装CentOS①下载CentOS②安装Linux有两种方式③下载模拟软件④安装vmware⑤创建虚拟机⑥安装操作系统Linux简述 在国内比较流行的两款Linux发行版本CentOS和ubuntu 它们的区别 ubuntu&#xff1a;页面更加的华丽比较漂亮&#xff0c;它对计算机…

【bioinfo】融合检测软件FusionMap分析流程和报告结果

文章目录写在前面FusionMap融合检测原理FusionMap与其他软比较FusionMap分析流程FusionMap结果文件说明FusionMap mono CUP设置图片来源: https://en.wikipedia.org/wiki/Fusion_gene写在前面 下面主要内容是关于RNA-seq数据分析融合&#xff0c;用到软件是FusionMap 【Fusion…

连接微信群、Slack 和 GitHub:社区开放沟通的基础设施搭建

NebulaGraph 社区如何构建工具让 Slack、WeChat 中宝贵的群聊讨论同步到公共领域。 要开放&#xff0c;不要封闭 在开源社区中&#xff0c;开放的一个重要意义是社区内的沟通、讨论应该是透明、包容并且方便所有成员访问的。这意味着社区中的任何人都应该能够参与讨论和决策过…

编写程序:有92号和95号汽油可以选择,选择你需要的汽油,并输入需要加油的升数,点击按钮“`计算总价钱`“在div中可以得到你所需要支付的价格

需求&#xff1a; 有92号汽油和95号可以选择&#xff0c;选择你需要的汽油&#xff0c;并输入需要加油的升数&#xff0c;点击按钮"计算总价钱"在div中可以得到你所需要支付的价格。结构如下图所示&#xff1a; 详细代码如下&#xff1a; <!DOCTYPE html> &l…

图像识别技术OpenCV | C++版本

基础入门 图像与信号 图像 图像是人对视觉感知的物质再现。图像可以由光学设备获取&#xff0c;也可以人为创作。随着数字采集技术和信号处理理论的发展&#xff0c;越来越多的图像以数字形式存储。因而&#xff0c;有些情况下”图像“一词实际上是指数字图像。图像相关的话…

YOLOv8初体验:检测、跟踪、模型部署

安装 YOLOv8有两种安装方式&#xff0c;一种是直接用pip命令安装&#xff1a; pip install ultralytics另外一种是通过源码安装&#xff1a; git clone https://github.com/ultralytics/ultralytics cd ultralytics pip install -e .[dev]安装完成后就可以通过yolo命令在命令…

JavaScript的错误类型数据

在使用JavaScript开发过程中&#xff0c;当我们遇见浏览器控制台中出现的报错时&#xff0c;如何从这些错误类型快速定位到问题代码是一种必不可少的技能&#xff0c;下面我们来看看JavaScript的7种错误类型&#xff08;卷起来…&#xff09; 1、SyntaxError&#xff1a;语法错…

IP地址、网段处理模块IPy

【小白从小学Python、C、Java】【计算机等级考试500强双证书】【Python-数据分析】IP地址、网段处理模块IPy选择题以下关于python代码表述错误的一项是?from IPy import IPprint("【执行】IP(192.168.0.0/24).len()")print(IP(192.168.0.0/24).len())print("【…

realman——使用Moveit控制Gazebo中的机械臂

文章目录 概述新建工作区配置说明MoveIt端的配置机器人端的配置关节轨迹控制器关节状态控制器运行效果可能存在的问题概述 MoveIt!与 Gazebo 的联合仿真,其主要思路为搭建 ros_control 和 MoveIt!的桥梁。先在 MoveIt!端配置关节和传感器接口 yaml 文件,将其加载到 rviz 端;…

Java 某厂面试题真题合集

哈喽~大家好&#xff0c;这篇来看看Java 某厂面试题真题合集。 &#x1f947;个人主页&#xff1a;个人主页​​​​​ &#x1f948; 系列专栏&#xff1a;【日常学习上的分享】 &#x1f949;与这篇相关的文章&#xff1a; Spr…

leetcode-70 爬楼梯(java实现)

爬楼梯题目分析1 递归写法动态规划解法题目 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 分析1 递归写法 如果要爬上第n阶&#xff0c;要么是从第n-1上面再爬1阶上去的&#xff0c;要么是从…

Postman简介及接口测试流程(小菜鸟攻略)

目录 前言 一、常见接口 二、前端和后端 三、什么是接口测试 四、接口组成 1、接口说明 2、调用url 3、请求方法&#xff08;get\post&#xff09; 4、请求参数、参数类型、请求参数说明 5、返回参数说明 五、为什么要做接口测试 本章主要介绍如何使用postman做接口…

电脑蓝屏怎么办?这5个技巧你必须学会

案例&#xff1a;电脑蓝屏是什么原因&#xff1f;怎么样可以解决&#xff1f; “救命&#xff01;&#xff01;&#xff01;电脑是怎么了&#xff1f;开机直接蓝屏&#xff0c;是哪里坏了吗&#xff1f;前几天电脑还是好的&#xff0c;今早一打开就是蓝屏&#xff0c;可能是之…