学习笔记整理-JS-06-函数

一、函数基本使用

1. 什么是函数

  • 函数就是语句的封装,可以让这些代码方便地被复用。
  • 函数具有"一次定义,多次调用"的优点。
  • 使用函数,可以简化代码,让代码更具有可读性。

2. 函数的定义和调用

  • 和变量类似,函数必须先定义然后才能使用

  • 使用function关键字定义函数,function是"功能"的意思。

      function fun() {
        // 函数体语句
      }
    
    • function:表示定义函数。
    • fun:函数名,函数名必须符合JS标识符命名规则。
    • ():圆括号中是形参列表,即使没有形参,也必须书写圆括号。
    • {}:大括号中就是函数体语句。
      var fun = function () {
        // 函数体语句
      }
    
    • function ():匿名函数
  • 函数的调用

    • 执行函数体中的所有语句,就称为"调用函数"
    • 调用函数非常简单,只需在函数名字后书写圆括号对即可
          fun()  // 调用函数,圆括号中是实参列表,如果没有实参,也要书写圆括号。
      
      fun.png
  • 函数声明的提升

    • 和变量声明提升类似,函数声明也可以被提升

         fun();
         function fun() {
            alert('函数被执行');
         } 
      
      • function fun()在预解析阶段会被提升。
    • 函数优先提升

      fun-1

3. 函数的参数和返回值

  • 参数是函数内的一些待定值,在调用函数时,必须传入这些参数的具体值
  • 函数的参数可多可少,函数可以没有参数,也可以有多个参数,多个参数之间需要用逗号隔开。
  • 函数的参数
      function add(a, b) { // 圆括号中定义"形式参数"
        var sum = a + b;
        console.log('两个数字的和是' + sum); 
      }
      add(3, 5); // 调用函数传入"实际参数"
    
    • 形参和实参个数不同的情况
      fun-2
    • arguments
      • 函数内arguments表示它接收到的实参列表,它是一个类数组对象
      • 类数组对象:所有属性均为从0开始的自然数序列,并且有length属性,和数组类似可以用方括号书写下标访问对象的某个属性值,
        但是不能调用数组的方法。
  • 函数的返回值
    • 函数体内可以使用return关键字表示"函数的返回值"
          function sum(a, b) {
            return a + b; // 函数的返回值
          }
          var result = sum(3, 5); // 函数的返回值可以被变量接受
      
    • 调用一个有返回值的函数,可以被当做一个普通值,从而可以出现在任何可以书写值的地方。
          function sum(a, b) {
            return a + b;
          }
          var result = sum(3, 4) * sum(2, 6);
      
          function sum(a, b) {
            return a + b;
          }
          var result = sum(3, sum(4, 5));
      
    • 遇见return即退出函数
      • 调用函数时,一旦遇见return语句则会立即退出函数,将执行权交给调用者。

二、函数算法题

1. 寻找喇叭花数

  • 喇叭花树是这样的三位数:其每一位数字的阶乘之和恰好等于它本身。即abc = a! + b! + c!,其中abc表示一个三位数。试寻找所有喇叭花树。

  • 思路:将计算某个数字的阶乘封装成函数,这样可以让问题简化。

          // 计算一个数字的阶乘
          function factorial(n) {
              // 累乘器
              var result = 1;
              for (var i = 1; i <= n; i++) {
                  result *= i;
              }
              return result;
          }
          // 穷举法,从100到999寻找喇叭花数
          for (var i = 100; i <= 999; i++) {
              // 把数字i变为字符串
              var i_str = i.toString();
              // abc分别表示百位、十位、个位
              var a = Number(i_str[0]);
              var b = Number(i_str[1]);
              var c = Number(i_str[2]);
              // 根据喇叭花数的条件,来判断
              if(factorial(a) + factorial(b) + factorial(c) == i){
                  console.log(i);
              }
          }      
    
  • sort内置排序函数

    • 数组排序可以使用sort()方法,这个方法的参数又是一个函数。
          var arr = [33, 22, 55, 11];
          arr.sort(function (a, b) {
          
          });
      
    • 这个函数中的a、b分别表述数组中靠前和靠后的项,如果需要它们交换位置,则返回任意正数;否则就返回负数。
         var arr = [33, 22, 55, 11];
         arr.sort(function (a, b) {
            if (a > b) {
              return 1;
            } else {
              return -1;
            }
         }) 
         // 从小到大
         arr.sort(function (a, b) {
           return a - b; 
         })
         // 从大到小
         arr.sort(function (a, b) {
           return b - a;
         })
      

三、递归

1. 什么是递归

  • 函数的内部语句可以调用这个函数自身,从而发起对函数的一次迭代。在新的迭代中,又会执行调用函数自身的语句,从而又产生一
    次迭代。当函数执行到某一次时,不再进行新的迭代,函数被一层一层返回,函数被递归。
  • 递归是一种较为高级的变成技巧,它把一个大型复杂的问题层层转化为一个原问题相似较小的问题来解决。
  • 递归的要素
    • 边界条件:确定递归到何时终止,也称为递归的出口。
    • 递归模式:大问题是如何分解为小问题的,也称为递归体。

2. 递归常见算法

  • 斐波那契数列
    • 斐波那契数列是这样的数列:1、1、2、3、5、8、13、21。
    • 数列下标为0和1的项的值都是1,从下标为2的项开始,每项等于前面两项的和。
      @code

3. 实现深克隆

@code

四、全局变量和局部变量

  • 变量作用域:JavaScript是函数作用域编程语言:变量只在其定义时所在的function内部有意义。

      function fun() {
        var a = 10;
      }
      fun();
      console.log(a); // 报错
    
    • 变量a是在fun函数中被定义的,所以变量a只在fun函数内部有定义,fun函数就是a的"作用域"变量a被称为局部变量
  • 全局变量

    • 如果不将变量定义在任何函数的内部,此时这个变量就是全局变量,它在任何函数内都可以被访问和更改。
        var a = 10;
        function fun() {
          a++;
          console.log(a); // 输出11
        }
        fun();
        console.log(a); // 输出11
      
      • 变量a没有定义在任何函数内部,它是"全局变量"。
  • 遮蔽效应

    • 如果函数中也定义了和全局同名的变量,则函数内的变量会将全局的变量"遮蔽"
         var a = 10;
         function fun() {
            var a = 5;
            a++;
            console.log(a); // 输出6
         }
         fun();
         console.log(a); // 输出 10
      
      • 局部变量a将全局变量a"遮蔽"了
    • 注意考虑变量声明提升的情况
         var a = 10;
         function fun() {
            a++;        // 局部变量a被自增1,a此时是undefined,自增1结果是NaN
            var a = 5;  // 局部变量a会被提升到a++之前, 重新将a赋值为5
            console.log(a); // 输出5
         }
         fun();
         console.log(a); // 输出10
      
  • 形参也是局部变量

      var a = 10;
      function fun(a) {
        a++;
        console.log(a); // 输出8
      }
      fun(7);
      console.log(a);  // 输出10
    
    • 形参a也是函数内部的局部变量

五、作用域链

  • 函数的嵌套:一个函数内部也可以定义一个函数。和局部变量类似,定义在一个函数内部的函数是局部函数。

        function fun() {
          function inner() {
              console.log('你好');
           }
           inner(); // 调用内部函数
        }
        fun();  // 调用外部函数
    
  • 作用域链

    • 在函数嵌套中,变量会从内到外逐层寻找它的定义。
        var a = 10;
        var b = 20;
        function fun() {
          var c = 30;
          function inner() {
            var a = 40;
            var d = 50;
            console.log(a, b, c, d); // 使用变量时,JS会从当前层开始,逐层向上寻找定义。
          }
          inner();
        }
        fun();
      
    • 不加var将定义全局变量
      • 在初次给变量赋值时,如果没有加var,则将定义全局变量。
          function fun() {
            a = 3;
          }
          fun();
          console.log(a); // 3
        
          var a = 1;
          var b = 2;
          function fun() {
            c = 3;
            var b = 4;
            b++;
            console.log(b); // 5
            c++;
          }
          fun();
          console.log(b); // 2
          console.log(c); // 4
        

六、闭包

  • 什么是闭包

        // 创建一个函数
        function fun() {
           // 定义局部变量
           var name = '张三';
           function innerFun() {
              alert(name);
           } 
           return innerFun; // 返回了内部函数
        }
        var innerFun = fun(); // 内部函数被移动到了外部执行
        innerFun();
    
    • JavaScript中函数会产生闭包(closure)。闭包是函数本身该函数声明时所处的环境状态的组合。
      closure.png

    • 函数能够"记忆住"其定义时所处的环境,即使函数不在其定义的环境中被调用,也能访问定义时所处环境的变量。

  • 观察闭包现象

    • 在JavaScript中,每次创建函数时都会创建闭包
    • 但是,闭包特性往往需要将函数"换一个地方"执行,才能被观察出来。
  • 闭包的作用

    • 闭包很有用,因为它允许我们将数据与操作该数据的函数关联起来,这与"面向对象编程"有少许相似之处。
    • 闭包的功能:记忆性、模拟私有变量。
  • 闭包的用途[记忆性]

    • 当闭包产生时,函数所处环境的状态会始终保持在内存中,不会在外层函数调用后被自动清除。这就是闭包的记忆性。
    • 举例:创建体温检测函数checkTemp(n),可以检查体温n是否正常,函数会返回布尔值。
      但是不同的小区有不同的体温检测标准,比如A小区体温合格线是37.1℃,而B小区体温合格线是37.3℃
          function createCheckTemp(standardTemp) {
            function checkTemp(n) {
              if (n <= standardTemp) {
                alert('你的体温正常');
              } else {
                alert('你的体温偏高');
              }
            }
            return checkTemp;
          }
          var checkTemp_A = createCheckTemp(37.1);
          var checkTemp_B = createCheckTemp(37.3);
          checkTemp_A(37.2);
          checkTemp_B(37.0);
          checkTemp_A(37.5); 
      
  • 闭包的用途[模拟私有变量]

    • 请定义一个变量a,要求是能保证这个a只能被进行指定操作(如加1、乘2),而不能进行其他操作。
        // 封装一个函数,这个函数的功能就是私有化变量
        function fun() {
           // 定义一个局部变量a
           var a = 0;
           return {
              getA: function() {
                return a;
              },
              add: function () {
                a++;
              },
              pow: function () {
                a *=2;
              }   
           }  
        }
        var obj = fun();
        // 如果想在fun函数外面使用变量a,唯一的方法就是调用getA()方法。
        console.log(obj.getA());   
      
  • 闭包的注意点

    • 不能滥用闭包,否则会造成网页的性能问题,严重时可能导致内存泄漏。所谓内存泄漏是指程序中已动态分配的内存由于某种原因未释放或
      无法释放。
  • 闭包的一道面试题

      function addCount() {
        var count = 0;
        return function () {
          count = count + 1;
          console.log(count);
        };
      }
      var fun1 = addCount();
      var fun2 = addCount();
      fun1(); // 1
      fun2(); // 1
      fun2(); // 2
      fun1(); // 2 
    

七、什么是IIFE

  • IIFE(Immediately Invoked Function Expression,立即调用函数表达式)是一种特殊的JavaScript函数写法,
    一旦被定义,就立即被调用

      (function () {
        statements
       })();
    
    • 包裹function的括号:将函数变成表达式
    • ():运行函数
  • 形成IIFE的方法

    • 函数不能直接加圆括号被调用
         function () {
          alert(1)     
         }()
      
    • 函数必须转为函数表达式才能被调用。
        (function (){
          alert(1)
        })();
      
        +function () {
          alert(1)
        }(); 
      
        -function () {
          alert(1)
        }();
      
  • IIFE的作用[为变量赋值]

    • 为变量赋值:当给变量赋值需要一些较为复杂的计算时(如if语句),使用IIFE显的语法更紧凑
      <!DOCTYPE html>
      <html lang="en">
      
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Document</title>
      </head>
      
      <body>
          <script>
              var age = 42;
              var sex = '女';
              var title = (function () {
                  if (age < 18) {
                      return '小朋友';
                  } else {
                      if (sex == '男') {
                          return '先生';
                      } else {
                          return '女士';
                      }
                  }
              })();
      
              alert(title);
          </script>
      </body>
      
      </html>
      
  • IIFE的作用[将全局变量变为局部变量]

    • IIFE可以在一些场合(如for循环中)将全局变量为局部变量,语法显得紧凑。
      <!DOCTYPE html>
      <html lang="en">
      
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Document</title>
      </head>
      
      <body>
          <script>
              var arr = [];
      
              for (var i = 0; i < 5; i++) {
                  (function(i){
                      arr.push(function () {
                          alert(i);
                      });
                  })(i);
              }
              arr[0]();
              arr[1]();
              arr[2]();
              arr[3]();
              arr[4]();
          </script>
      </body>
      
      </html>
      

八、内容难点

  • 什么是函数?函数为开发带来了哪些便利?
  • 函数的参数和返回值
  • 函数的相关算法题
  • 递归、递归算法题
  • 作用域和闭包
  • IIFE

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

选择最适合自己的笔记本

选择最适合自己的笔记本电脑 一、了解笔记本品牌一线品牌准一线品牌二线品牌三线品牌 二、笔记本入手渠道笔记本入手渠道 三、根据需求选择机型使用需求1.日常使用2.商务办公、财务3.轻度剪辑、ps4.代码5.创意设计6.游戏 四、笔记本电脑配置如何选1.cpu2.显卡&#xff08;GPU&a…

MSP432自主开发笔记6:定时器多通道捕获多条编码器线脉冲数

所用开发板&#xff1a;MSP432P401R 今日在此更新一下编码器测速的定时器捕获写法&#xff0c;之前学习时竟然忘记更新了~~ 本文讲如何用定时器的通道来 捕获编码器的脉冲信号数量&#xff0c;不提供速度路程的计算方式&#xff0c; 文章提供源码&#xff0c;测试工程下载&a…

Jmeter 参数化的几种方法

目录 配置元件-用户自定义变量 前置处理器-用户参数 配置元件-CSV Data Set Config Tools-函数助手 配置元件-用户自定义变量 可在测试计划、线程组、HTTP请求下创建用户定义的变量 全局变量&#xff0c;可以跨线程组调用 jmeter执行的时候&#xff0c;只获取一次&#xff0…

PromQL实现Actuator获取的JVM指标的Full GC次数监控

Spring Boot 版本需要2.0.0或更高版本。 添加Micrometer Prometheus registry依赖: <dependency><groupId>io.micrometer</groupId><artifactId>micrometer-registry-prometheus</artifactId> </dependency>在application.properties中开…

linux-删除KVM虚拟机

1.查看主机 #virsh list 2.关闭主机 #virsh shutdown 虚拟机名称 3.删除主机定义 #virsh undefine 虚拟机名称 4.删除KVM虚拟机文件 #find / -name 虚拟机名称 #rm -rf 虚拟机文件

WebSocket与消息推送

B/S结构的软件项目中有时客户端需要实时的获得服务器消息&#xff0c;但默认HTTP协议只支持请求响应模式&#xff0c;这样做可以简化Web服务器&#xff0c;减少服务器的负担&#xff0c;加快响应速度&#xff0c;因为服务器不需要与客户端长时间建立一个通信链接&#xff0c;但…

原生js发送ajax请求---ajax请求篇(一)

在原生js中我们使用的是XMLHttpRequest对象来发送ajax请求 主要步骤就是&#xff1a; 1.创建XMLHTTPRequest对象 2.使用open方法设置和服务器的交互信息 3.设置发送的数据&#xff0c;开始和服务器端交互 4.注册事件 5.更新界面 &#xff08;1&#xff09; get方式 //步骤一…

教你如何为博客网站申请阿里云的免费域名HTTPS证书

如何为博客网站申请阿里云的免费域名HTTPS证书 文章目录 如何为博客网站申请阿里云的免费域名HTTPS证书前置条件&#xff1a;步骤1 例如阿里云控制台&#xff0c;选择SSL证书步骤2 申请购买免费证书步骤3 创建证书步骤3.1 证书申请步骤3.2 DNS域名验证 步骤4 等待证书审核成功&…

善于用兵的人,军队粮草取自敌人

善于用兵的人&#xff0c;军队粮草取自敌人 【安志强趣讲《孙子兵法》第8讲】 【原文】 善用兵者&#xff0c;役不再籍&#xff0c;粮不三载&#xff1b;取用于国&#xff0c;因粮于敌&#xff0c;故军食可足也。 【注释】 役不再籍&#xff1a;役&#xff0c;兵役&#xff1b;…

一周开发问题回顾(2023年08月07日-2023年08月13日)

一周开发问题回顾2023年08月07日-2023年08月13日 1. Arrays.asList()与 new ArrayList()的区别1.1 Arrays1.1.1补充 ArrayList(Arrays.asList(array)) 1.2 ArrayList()1.2.1 创建ArrayList的几种方法 2.Mysql中group by的使用方式3.画图4. 时间倒排5. 工厂策略设计模式6.List注…

Observable设计模式简介

Observable设计模式存在于许多Java API和响应式编程中。下面介绍Java中永恒的Observable模式。 Observable设计模式用于许多重要的Java API。一个众所周知的示例是使用ActionListenerAPI执行操作的JButton。在这个例子中&#xff0c;我们ActionListener在按钮上进行了监听或…

2.Model、ModelMap和ModelAndView的使用详解

1.前言 最近SSM框架开发web项目&#xff0c;用得比较火热。spring-MVC肯定用过&#xff0c;在请求处理方法可出现和返回的参数类型中&#xff0c;最重要就是Model和ModelAndView了&#xff0c;对于MVC框架&#xff0c;控制器Controller执行业务逻辑&#xff0c;用于产生模型数据…

汽车制造业上下游协作时 外发数据如何防泄露?

数据文件是制造业企业的核心竞争力&#xff0c;一旦发生数据外泄&#xff0c;就会给企业造成经济损失&#xff0c;严重的&#xff0c;可能会带来知识产权剽窃损害、名誉伤害等。汽车制造业&#xff0c;会涉及到重要的汽车设计图纸&#xff0c;像小米发送汽车设计图纸外泄事件并…

电子拣货标签2代系统简介

CK_Label_v2 一、革新点 无线 容易安装和移动 按键及指示导引系统 128*64点阵屏幕&#xff0c;自带LED背光 红绿两色高亮LED灯光指示 长电池寿命&#xff0c;常规使用3年以上 二、特点与效益 提升作业速度与品质 简易快速部署 实现无纸化标准化作业 缩短操作人员培训时…

Jmeter-压力测试工具

文章目录 Jmeter快速入门1.1.下载1.2.解压1.3.运行 2.快速入门2.1.设置中文语言2.2.基本用法 Jmeter快速入门 1s内发送大量请求&#xff0c;模拟高QPS&#xff0c;用以测试网站能承受的压力有多大 Jmeter依赖于JDK&#xff0c;所以必须确保当前计算机上已经安装了JDK&#xff0…

docker的服务/容器缺少vim问题

背景/问题&#xff1a; docker的服务/容器缺少vim问题 bash: vim: command not found 在docker的mysql服务中安装Vim 1、执行apt-get update root6d8d17e320a0:/# apt-get update问题:文件下载失败 Err:1 http://security.debian.org/debian-security buster/updates InRe…

顺序表的插入,删除,修改和查找(详细解析)

目录 一.顺序表的初始化----静态分配 二.顺序表的初始化----动态分配 三.顺序表的插入 1.插入操作 2.插入操作的时间复杂度 三.顺序表的删除操作 1.顺序表的删除 2.删除操作的时间复杂度 四.顺序表的查找 1.按位查找操作&#xff1a;查找第i位置的元素 2.按位查找操作…

c++字符串函数

在 C 中有大量用于操作 C-style 字符串的函数&#xff0c;它们集成在头文件 <cstring> 中。其常见的函 函数作用strcpy(s1,s2) 复制字符串 s2 到 s1strcat(s1,s2) 将字符串 s2 连接到 s1 末尾strlen(s) 计算字符串 s 长度strcmp(s1,s2) 比较字符串 s1 和 s2 …