学习笔记整理-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结果是NaNvar a = 5;  // 局部变量a会被提升到a++之前, 重新将a赋值为5console.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); // 5c++;}fun();console.log(b); // 2console.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() {// 定义一个局部变量avar 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(); // 1fun2(); // 1fun2(); // 2fun1(); // 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.hqwc.cn/news/66483.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

webpack性能优化

代码分离 代码分离是webpack中一个非常重要的特性&#xff1a; 它主要的目的是将代码分离到不同的bundle中&#xff0c;之后我们可以按需加载&#xff0c;或者并行加载这些文件比如默认情况下&#xff0c;所有的JavaScript代码&#xff08;业务代码、第三方依赖、暂时没有用到…

Netty:channel的事件顺序

服务端&#xff1a;正常启动的channel事件顺序 REGISTERED -> BIND -> ACTIVE 客户端&#xff1a;正常启动的channel事件顺序 REGISTERED -> CONNECT -> ACTIVE 服务端&#xff1a;接收到客户端连接&#xff0c;为客户端分配的channel的事件顺序 REGISTERED…

日常BUG—— SpringBoot项目DEBUG模式启动慢、卡死。

&#x1f61c;作 者&#xff1a;是江迪呀✒️本文关键词&#xff1a;日常BUG、BUG、问题分析☀️每日 一言 &#xff1a;存在错误说明你在进步&#xff01; 一、问题描述 我们调试程序时&#xff0c;需要使用DEBUG模式启动SpringBoot项目&#xff0c; 有时候会发…

【Mybatis】调试查看执行的 SQL 语句

1. 问题场景&#xff1a; 记录日常开发过程中 Mybatis 调试 SQL 语句&#xff0c;想要查看Mybatis 中执行的 SQL语句&#xff0c;导致定位问题困难 2. 解决方式 双击shift找到mybatis源码中的 MappedStatement的getBoundSql()方法 public BoundSql getBoundSql(Object para…

Unity开发笔记:截取指定位置含有UI的场景截图并输出

学习记录整理&#xff0c;自用&#xff0c;也希望能帮助到有相同需求的人。 如果直接截全图&#xff1a; string screenshotName "Assets/Textures/UI/20230803/2.png";ScreenCapture.CaptureScreenshot(screenshotName);截取指定位置含有UI的场景截图&#xff1a; …

概念解析 | 知识蒸馏(Knowledge Distillation)

教师指点弟子 - 深度神经网络知识蒸馏技术详解 注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:知识蒸馏(Knowledge Distillation)。 Knowledge Distillation(知识蒸馏)Review–20篇paper回顾- 知乎 知识蒸馏(Knowledge Dist…

大专同事,7天开发了一套应用管理系统

目录 一、前言 二、如何基于工具实现应用开发&#xff1f; 三、低代码基本功能及操作 体验过程&#xff1a; 01、连接数据源 02、设计表单 03、流程设计 04、图表呈现 05、组织架构设置 五、效率评价 六、小结 一、前言 众所周知&#xff0c;每家公司在发展过程中都需要构建大量…

使用雅克比矩阵计算Rossler映射的lyapunov exponent图谱

Rossler映射如下: 雅可比行列式方法 计算Henon映射的Lyapunov exponent图谱,算法描述为: 0:初始化:初始化用到的值。参数a:[0,1.4],b:0.3,初始值x和y:1,迭代次数M:2000。 1:遍历参数a:计算不同a值所对应的Henon映射的Lyapunov exponent图谱。 2:迭代M次:…

HTML和JavaScript实现一个简单的计算器

使用HTML和JavaScript实现一个简单的计算器。 一、绘制键盘 <!DOCTYPE html> <html> <head><title>Simple Calculator</title><style>.calculator {display: grid;grid-template-columns: repeat(4, 1fr);grid-gap: 5px;padding: 10px;}.…

使用chatGPT生成提示词,在文心一言生成装修概念图

介绍 家是情感的港湾&#xff0c;而家居装修则是将情感融入空间的艺术。如何在有限的空间里展现个性与美感&#xff0c;成为了现代人关注的焦点。而今&#xff0c;随着人工智能的发展&#xff0c;我们发现了一个新的创意助手——ChatGPT&#xff0c;它不仅为我们带来了更多可能…

锐捷无线产品运维

目录 登录AP产品 Console登录&#xff08;只可以现场登录&#xff09; Web/Telnet/SSH登录&#xff08;可以现场、远程登录&#xff09; 配置AP的管理地址 通过Web界面远程登录 通过Telnet、SSH等命令行的方式登录 登录AC产品 Console登录&#xff08;只可以现场登录&a…

如何预防ssl中间人攻击?

当我们连上公共WiFi打开网页或邮箱时&#xff0c;殊不知此时可能有人正在监视着我们的各种网络活动。打开账户网页那一瞬间&#xff0c;不法分子可能已经盗取了我们的银行凭证、家庭住址、电子邮件和联系人信息&#xff0c;而这一切我们却毫不知情。这是一种网络上常见的“中间…