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

news2024/12/26 9:29:20

一、函数基本使用

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

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

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

相关文章

C++:模拟实现list及迭代器类模板优化方法

文章目录 迭代器模拟实现 本篇模拟实现简单的list和一些其他注意的点 迭代器 如下所示是利用拷贝构造将一个链表中的数据挪动到另外一个链表中&#xff0c;构造两个相同的链表 list(const list<T>& lt) {emptyinit();for (auto e : lt){push_back(e);} }void test_…

【ES】【elasticsearch】分布式搜索

文章目录 ☀️安装elasticsearch☀️1.部署单点es&#x1f338;1.1.创建网络&#x1f338;1.2.下载镜像&#x1f338;1.3.运行 ☀️2.部署kibana&#x1f338;2.1.部署&#x1f338;2.2.DevTools ☀️3.安装IK分词器&#x1f338;3.1.在线安装ik插件&#xff08;较慢&#xff0…

ARM汇编快速入门

本文主要分享如何快速上手ARM汇编开发的经验、汇编开发中常见的Bug以及Debug方法、用的Convolution Dephtwise算子的汇编实现相对于C版本的加速效果三方面内容。 前言 神经网络模型能够在移动端实现快速推理离不开高性能算子&#xff0c;直接使用ARM汇编指令来进行算子开发无疑…

ad+硬件每日学习十个知识点(32)23.8.12 (元器件封装、PCB封装、3D的PCB封装)

文章目录 1.元器件封装属性值说明2.PCB封装标准说明&#xff08;M、N、L&#xff09;3.电阻的PCB封装&#xff08;阻焊层&#xff09;4.电感的PCB封装&#xff08;CD、CDRH&#xff09;1.CD31的意思是&#xff0c;直径3mm&#xff0c;高度1mm![在这里插入图片描述](https://img…

【SQL应知应会】索引(二)• MySQL版

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习&#xff0c;有基础也有进阶&#xff0c;有MySQL也有Oracle 索引 • MySQL版 前言一、索引1.简介2.创建2.1 索引…

Gradio——快速部署可视化人智能应用

前言 Gradio是一个开源的Python库&#xff0c;用于快速构建机器学习和数据科学演示的应用。它可以帮助你快速创建一个简单漂亮的用户界面&#xff0c;以便向客户、合作者、用户或学生展示你的机器学习模型。此外&#xff0c;还可以通过自动共享链接快速部署模型&#xff0c;并获…

IntelliJ IDEA热部署:JRebel插件的安装与使用

热部署 概述JRebel 概述 热部署&#xff0c;指修改代码后&#xff0c;无需停止应用程序&#xff0c;即可使修改后的代码生效&#xff0c;其有利于提高开发效率。 热部署方式&#xff1a; 手动热部署&#xff1a;修改代码后&#xff0c;重新编译项目&#xff0c;然后启动应用程…

【软件测试】Linux系统下安装jdk配置环境变量(详细步骤)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、安装环境 操作…

UGUI事件系统EventSystem

一. 事件系统概述 Unity的事件系统具有通过鼠标、键盘、游戏控制柄、触摸操作等输入方式&#xff0c;将事件发送给对象的功能。事件系统通过场景中EventSystem对象的组件EventSystem和Standalone Input Module发挥功能。EventSystem对象通常实在创建画布的同时被创建的&#xf…

c++杂谈-5

目录 一、一些c11新特性1. decltype关键字及函数后置返回类型2. 函数后置返回类型 二、c的内存模型三、函数指针和回调函数四、函数模版的注意事项 一、一些c11新特性 1. decltype关键字及函数后置返回类型 在C11中&#xff0c;decltype操作符&#xff0c;用于查询表达式的数…

HarmonyOS NEXT新能力,一站式高效开发HarmonyOS应用

2023年8月6日华为开发者大会2023&#xff08;HDC.Together&#xff09;圆满收官&#xff0c;伴随着HarmonyOS 4的发布&#xff0c;华为向开发者发布了汇聚所有最新开发能力的HarmonyOS NEXT开发者预览版&#xff0c;并分享了围绕“一次开发&#xff0c;多端部署” “可分可合&a…

通过Microsoft Loopback Adapter实现虚拟机和物理机的通信

问题 问&#xff1a;不借助路由器或交换机的情况下&#xff0c;能不能实现主机和虚拟及之间两个软件的通信呢&#xff1f;要求主机和虚拟及均有独立的ip地址&#xff0c;从而进行指定源的组播通信。 答&#xff1a;可以。通过借助虚拟网络适配器&#xff0c;不需要路由器或交…

深度思考rpc框架面经系列之三

6 一个rpc框架的请求调用的流程&#xff08;小红书面试&#xff09; 6.1 讲讲rpc调用原理&#xff0c;比如服务怎么发现&#xff0c;怎么调用&#xff0c;提供者怎么响应。怎么去请求&#xff0c;又怎么回来的 一个RPC&#xff08;远程过程调用&#xff09;框架的核心目的是允…

百度飞浆实战-手写数字识别

目录 参考建模过程1、数据加载和预处理2、模型的网络设计和开发模型组网 3、模型训练 代码实战1、打开aistudio找到项目 参考 视频教程 PaddleAPI DOC 建模过程 1、数据加载和预处理 飞桨框架帮助我们将MNIST数据集进行了内置 数据集名称&#xff1a; MNIST 数据集官网 &am…

2023-08-14 LeetCode每日一题(合并二叉树)

2023-08-14每日一题 一、题目编号 617. 合并二叉树二、题目链接 点击跳转到题目位置 三、题目描述 给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#xff08;而另一些不会…

Android布局【RelativeLayout】

文章目录 介绍常见属性根据父容器定位根据兄弟组件定位 通用属性margin 设置组件与父容器的边距padding 设置组件内部元素的边距 项目结构主要代码 介绍 RelativeLayout是一个相对布局&#xff0c;如果不指定对齐位置&#xff0c;都是默认相对于父容器的左上角的开始布局 常见…

3D沉浸式旅游网站开发案例复盘【Three.js】

Plongez dans Lyon网站终于上线了。 我们与 Danka 团队和 Nico Icecream 共同努力&#xff0c;打造了一个令我们特别自豪的流畅的沉浸式网站。 这个网站是专为 ONLYON Tourism 和会议而建&#xff0c;旨在展示里昂最具标志性的活动场所。观看简短的介绍视频后&#xff0c;用户…

[足式机器人]Part5 机械设计 Ch00/01 绪论+机器结构组成与连接 ——【课程笔记】

本文仅供学习使用 本文参考&#xff1a; 《机械设计》 王德伦 马雅丽课件与日常作业可登录网址 http://edu.bell-lab.com/manage/#/login&#xff0c;选择观摩登录&#xff0c;查看2023机械设计2。 机械设计-Ch00Ch01——绪论机器结构组成与连接 Ch00-绪论0.1 何为机械设计——…

设计HTML5列表和超链接

在网页中&#xff0c;大部分信息都是列表结构&#xff0c;如菜单栏、图文列表、分类导航、新闻列表、栏目列表等。HTML5定义了一套列表标签&#xff0c;通过列表结构实现对网页信息的合理排版。另外&#xff0c;网页中还包含大量超链接&#xff0c;通过它实现网页、位置的跳转&…

ChatGPT爆火,会给教育带来什么样的影响或者冲击?

近来&#xff0c;人工智能聊天机器人ChatGPT连上热搜&#xff0c;火爆全网。ChatGPT拥有强大的信息整合能力、自然语言处理能力&#xff0c;可谓是“上知天文&#xff0c;下知地理”&#xff0c;而且还能根据要求进行聊天、撰写文章等。 ChatGPT一经推出&#xff0c;便迅速在社…