JavaScript基础第六天

148 阅读6分钟

函数

定义:

函数: function,是被设计为执行特定任务的代码块,可以实现代码复用,提高开发效率

**说明:**函数可以把具有相同或相似逻辑的代码“包裹”起来,通过函数调用执行这些被“包裹”的代码逻辑,这么做的优势是有利于精简代码方便复用。

函数使用

①声明语法

function 函数名(){
    函数体
}

例:

function sayHi(){
    console.log('hai~~')
}

②函数名命名规范

  • 和变量命名基本一致
  • 尽量小驼峰式命名法
  • 前缀应该为动词
  • 命名建议:常用动词约定
function getName() {}
function addSquares() {}

1648829563358

③调用语法

  • 注意:声明(定义)的函数必须调用才会真正被执行,使用 () 调用函数

  • 我们曾经使用的 alert() , parseInt() 这种名字后面跟小括号的本质都是函数的调用

函数名()
	<script>
        //函数声明
        function sayHi() {
            document.write('早上好');
            document.write('中午好');
            document.write('晚上好');
        }
        //函数调用
        sayHi();
        sayHi();
    </script>

④函数体

函数体是函数的构成部分,它负责将相同或相似代码“包裹”起来,直到函数调用时函数体内的代码才会被执行。函数的功能代码都要写在函数体当中。

function sayHi(){
    console.log('嗨~'); //函数体
}
sayHi()

⑤封装函数案例

<script>
     //需求:把99乘法表封装到函数里面,重复调用3次
      function multiplication() {
        for (let index = 1; index <= 9; index++) {
       	 for (let index1 = 1; index1 <= index; index1++) {
          let num = index1 * index;
          document.write(`<span>  ${index1} * ${index} = ${num} </span>`);
        }
         document.write('<br/>');
      }
      }	
      multiplication();
      multiplication();
      multiplication();
 </script>

函数传参

①函数声明

参数列表

  • 传入数据列表
  • 声明这个函数需要传入几个数据
  • 多个数据用逗号隔开
function 函数名 (参数列表){
    函数体
}

②函数调用

调用函数时,需要传入几个数据就写几个,用逗号隔开

函数名(传递的参数列表)

③形参和实参

  • 形参:声明函数时写在函数名右边小括号里的叫形参(形式上的参数)
  • 实参:调用函数时写在函数名右边小括号里的叫实参(实际上的参数)
  • 形参可以理解为是在这个函数内声明的变量(比如 num1 = 10)实参可以理解为是给这个变量赋值
  • 开发中尽量保持形参和实参个数一致
  • 我们曾经使用过的 alert('打印'), parseInt('11'), Number('11') 本质上都是函数调用的传参

④语法及案例

例:可单个参数,也可以多个参数

<script>
                        //形参
        function getSum(num1, num2) {
            console.log(num1 + num2);
        }
                //实参
        getSum(11, 22);//调用语法
        getSum(66, 66);
        getSum(99, 99);
    </script>
<script>
        //需求:学生的分数是一个数组,计算每个学生的总分 
        // let arr1 = [];
        // let arr2 = [];
        function getSum(arr) {
            let sum =0;
            for (let i = 0; i < arr.length; i++) {
                sum += arr[i];
            }
            console.log(sum);
        }

        let arr1 = [11, 22, 33, 44, 55, 66, 77];
        let arr2 = [12, 432, 66, 77, 99, 22, 55]
        
        getSum(arr1);
        getSum(arr2);
    </script>

函数返回值

①为什么要让函数有返回值

有些函数没有返回值的话:

  • 缺点:把计算后的结果处理方式写死了,内部处理了

  • 解决:把处理结果返回给调用者

  • l所以要根据需求,来设定需不需要返回值

有返回值函数的概念:

  • 当调用某个函数,这个函数会返回一个结果出来
  • 这就是有返回值的函数

②用return返回数据

  • 当函数需要返回数据出去时,用return关键字
<script>
      // function getMax() {}

      // function getSum() {}

      // // 这个num1 就是  函数getMax调用的返回值 ( num1 = 1 2 。。)

      // // let num2 = getSum();

      // let num1 = getMax();// 我们自己写的函数 只能返回 undefined
      // let num3 = parseInt(1.3);// js自己内部写的 返回值  1

      // console.log(num3); //

      function getMax() {
        // 100 就是 函数在执行完毕的时候 会返回的数据
        return 300;
      }

      let num1 = getMax(); // num1 =100

      console.log(num1);
    </script>

③细节:

  • 在函数体中使用 return 关键字能将内部的执行结果交给函数外部使用
  • 函数内部只能运行到 1 次 return,并且 return 后面代码不会再被执行,所以 return 后面的数据不要换行写
  • return会立即结束当前函数
  • 函数可以没有 return ,这种情况函数默认返回值为 undefined

作用域

①作用域概述

  • 通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。

Ⅰ、全局作用域

  • 范围:全局有效
  • 作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件

Ⅱ、局部作用域

  • 局部有效
  • 作用于函数内的代码环境,就是局部作用域。 因为跟函数有关系,所以也称为函数作用域

Ⅲ、块级作用域

  • {}内有效
  • 块作用域由 { } 包括,if语句和for语句里面的{ }等
 <script>
      // script标签内的运行环境就是全局作用域
      let num = 100; // 全局作用域
      function getMax() {
        // 这个区域内就不属于全局作用域
        // 局部作用域 或者 也叫做 函数作用域
        let num2 = 200;
      }
      for (let index = 0; index < 4; index++) {
        // 块级作用域
      }
      while (true) {
        // 块级作用域
      }
      if (true) {
        // 块级作用域
      }
    </script>

②变量的作用域

  • 在JavaScript中,根据作用域的不同,变量可以分为

Ⅰ、全局变量

  • 函数外部let 的变量
  • 全局变量在变量定义之后区域可以访问和修改
<script>
      // 直接写在全局作用域下的变量 =  全局变量  在任意的地方来访问
      let num = 100; // 全局变量   在任何地方都可以访问 
      function getMax() {
        console.log('函数 访问全局变量', num);
      }
      getMax();
      for (let index = 0; index < 2; index++) {
        console.log('for循环内 块级作用域 访问全局变量', num);
      }
      if(true){
        console.log("if语句 也 可以访问全局变量",num);
      }
    </script>

全局变量补充:

  • 定义一个变量 没使用 let 关键字 那么它就是一个全局变量
  • 都建议 定义变量的时候 都要记得使用let ,不用去记这么规则
<script>
      // userName = '索隆';
      // console.log(userName);
      function func1() {
        //  userName = '索隆'; // 全局变量 没有使用let 关键字 
        let userName = '索隆'; // 局部变量
      }
      func1();
      console.log(userName); // 报错
    </script>

Ⅱ、局部变量

  • 函数内部let的变量
  • 局部变量只能在当前函数内部访问和修改
<script>
      // 局部变量
      // 如果是在函数内部定义的变量 就叫做局部变量
      // 局部变量 不能在 它的大括号之外使用的,否则就会报错!! 
  
      let msg = 10000; // 全局变量

      // 局部变量  函数内部 声明的变量
      function getMax() {
        // 声明一个数字
        let num = 200; // 局部变量
      }
      // 局部变量 不能在 超出它的大括号来使用
      console.log(num); // 会报错 
    </script>

Ⅲ、块级变量

  • {} 内部的let变量
  • let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问
 <script>
      // 块级变量 就是我们在块级作用域内 定义的变量
      // 块级变量 类似局部变量,也是超出了自身的大括号 不能使用

      // for (let index = 0; index < 2; index++) {
      //   // num 块级变量 
      //   let num = 100;
      // }
      // console.log(num);// 使用块级变量  出错!! 


      // {
      //   let num =10;
      // }
      // {
      //   console.log(num);
      // }

    </script>

Ⅳ、变量作用域特殊情况:

  • 如果函数内部或者块级作用域内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐
  • 函数内部的形参可以看做是局部变量,所以形参相当于函数内部定义的局部变量,只有在函数内部可以使用

Ⅴ、小结

  • 分类 分成两类:

    ① 全局变量 直接放在 script标签内的变量 ②局部变量 用大括号包起来的变量 函数内部变量 块级变量

函数的嵌套使用

 <script>
      function func1() {
        console.log('func1');
        func2();
      }
      function func2() {
        console.log('func2');
        func3();
      }
      function func3() {
        console.log('func3');
      }
      func1(); // 输出什么  1
    </script>

作用域链

  • 只要是代码,就至少有一个作用域
  • 写在函数内部的局部作用域
  • 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
  • 根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链
  • 作用域链:根据函数的定义采取就近原则的方式来查找变量最终的值(不是根据函数的调用)
<script>
      // let num = 100;
      // function func1() {
      //   let num = 200;
      //   fun2();
      // }

      // function fun2() {
      //   let num = 300;
      //   console.log(num); // 300
      // }

      // func1();

      // 判断当前变量 输出是什么  
      // 就近原则   判断是要根据 函数的定义 来判断 而不是函数的调用 
      // 函数的定义 代码位置来判断  100  这个!! 
   
      let num = 100;
      function func1() {
        let num = 200;
        // 函数的调用 
        fun2();
      }

      // 函数的定义-声明 
      function fun2() {
        console.log(num);
      }

      func1();
    </script>

匿名函数(了解)

函数分为:

  • 具名函数

    声明:function fn() {}

    调用:fn()

  • 匿名函数:

    function() {}

匿名函数:将匿名函数赋值给一个变量,并且通过变量名称进行调用 我们将这个称为函数表达式

语法与调用:

函数的形参和实参使用跟具名函数一致

//声明
let fn = function () {
    函数体
}
//调用
fn()//函数名
// 匿名函数
      function () {
      // 设置 页面的标题 =  月薪过万
      document.title = '月薪过万';
       // 设置 页面的背景颜色 =  黄色
      document.body.style.backgroundColor = 'yellow';
       }

自执行函数(了解)

  • 避免全局变量之间的污染

  • 注意: 多个立即执行函数要用 ; 隔开,要不然会报错

  • 适合做一次性的任务- 不希望这个函数可以得到复用!!! 函数包装多段代码 让程序比较简洁

语法:

//方式1
(function () { console.log(11)})();

//方式2
(function () { console.log(11)}());

//不需要调用,立即执行
	//1 页面打开时候
        //1 设置 页面的标题 =  月薪过万
        //2 设置 页面的背景颜色 =  黄色 

let msg = 123;
      // 自执行函数
     (function () {
        let msg = 123;
       // 设置 页面的标题 =  月薪过万
        document.title = '月薪过万';
      // 设置 页面的背景颜色 =  黄色
         document.body.style.backgroundColor = 'yellow';
       })();

      console.log(msg);