JavaScript函数

1、函数的使用方法

(1)函数概念
函数:用于封装一段完成特定功能的代码。
相当于将一条或多条语句组成的代码块包裹起来,用户在使用时只需关心参数和返回值,就能完成特定的功能,而不用了解具体的实现。
(2)内置函数

<script>
  console.log(parseFloat('7.26e-2'));     // 返回解析后的浮点数:0.0726
  console.log(isNaN(' '));                // 判断是否是NaN:false
  console.log(parseInt('15.99'));
</script>

parseFloat()用于返回解析字符串后的浮点数。
isNaN()判断给定参数是否为NaN,判断结果为是,返回true,否则返回false。
parseInt()用于返回解析字符串后的整数值。
(3)自定义函数
除了使用内置函数外,JavaScript中还可以根据具体情况自定义函数,提高代码的复用性、降低程序维护的难度。
函数的定义由以下4部分组成:
关键字function。
函数名。
参数。
函数体。

自定义函数格式
function:定义函数的关键字。
函数名:可由大小写字母、数字、下划线(_)和$符号组成,但是函数名不能以数字开头,且不能是JavaScript中的关键字。
参数:是外界传递给函数的值,它是可选的,多个参数之间使用“,”分割。
函数体:是专门用于实现特定功能的主体,由一条或多条语句组成。
返回值:在调用函数后若想得到处理结果,在函数体中可用return关键字返回。

无参函数:适用于不需要提供任何数据,即可完成指定功能的情况。

<script>
  function greet() {
    console.log('Hello everybody!');
  }
</script>

有参函数:适用于开发时函数体内的操作需要用户传递数据的情况。

<script>
  function maxNum(a, b) {
    a = parseInt(a);
    b = parseInt(b);
    return a >= b ? a : b;
  }
</script>

形参:指的就是形式参数,具有特定的含义,在定义有参函数时设置的参数。
实参:指的是实际参数,也就是具体的值,在函数调用时传递的参数。
(4)arguments对象
获取函数调用时传递的所有实参:适用于开发时函数体形参不确定的情况。
实现方式:利用arguments对象,在函数体内可获取函数调用时传递的实参。
其他操作:length属性可获取实参的总数,具体实参值可利用数组遍历方式。

<script>
		// arguments 伪数组形式
        // 1、具有length属性
        // 2、通过索引存储数据;
        // 3、不具备 pop()\push()...
  function transferParam() {
    console.log(arguments.length);    // 获取用户实际传递的参数数量
    console.log(arguments);           // 在控制台输出用户调用函数时传递的参数
  }
</script>

(5)含有默认值的参数
函数的形参在设置时,还可以为其指定默认值。当调用者未传递该参数时,函数将使用默认值进行操作。

<script>
  function greet(name, say = 'Hi, I\'m ') {
    console.log(say + name);
  }
</script>

(6)剩余参数(不确定参数数量)
可用“…变量名”的方式动态接收用户传递的不确定数量的实参。

<script>
  function transferParam(num1, ...theNums) {
    theNums.unshift(num1);      // 在剩余参数数组的头部添加第一个参数
    console.log(theNums);       // 在控制台输出用户调用函数时传递的参数
  }
  transferParam()
</script>

<script>
  function transferParam(...theNums) {
    console.log(theNums);       // 在控制台输出用户调用函数时传递的参数
  }
  transferParam()
</script>

(7)变量的调用

<script>
  function sum(num1, num2) {    // 定义函数表达式,求和
    return num1 + num2;
  };
  sum(12,13);                                  // 调用函数
</script>

2、变量的作用域

总结:变量的使用是有作用域范围的。
作用域划分:全局作用域、函数作用域和块级作用域(ES6提供的)。
不同作用域对应的变量:全局变量、局部变量、块级变量(ES6提供的)。
变量作用域
全局变量:不在任何函数内声明的变量(显示定义)或在函数内省略var声明变量(隐式定义)都称为全局变量。
作用范围:它在同一个页面文件中的所有脚本内都可以使用。
全局变量
局部变量:在函数体内利用var关键字定义的变量称为局部变量,它仅在该函数体内有效。
局部变量
块级变量:ES6提供的let关键字声明的变量称为块级变量,仅在“{}”中间有效,如if、for或while语句等。
块级变量

<script>
  var a = 'one';                   // 全局变量
  function test() {
    var a = 'two';                 // 局部变量
    console.log(a);
  }
  test();
  for (let a = 0; a < 3; ++a) {    // 块级变量(ES6新增)
    console.log(a);
  }
  console.log(a);
</script>

垃圾回收机制
在JavaScript中,局部变量只有在函数的执行过程中存在,而在这个过程中会为局部变量在(栈或堆)内存上分配相应的空间,以存储它们的值,然后在函数中使用这些变量,直到函数结束。而一旦函数执行结束,局部变量就没有存在必要了,此时JavaScript就会通过垃圾回收机制自动释放它们所占用的内存空间。

<script>
//在开发中若要保留局部变量的值,可以通过以下两种方式实现:
  // 第1种方式:利用return返回
  function test(num) {
    num = num + 1;
    return num;
  }
  var num = test(24);
  console.log(num);       // 输出结果:25
</script>

<script>
  // 第2种方式:利用全局变量保存
  var memory;
  function test(num) {
    memory = num + 1;
  }
  test(24);
  console.log(memory);    // 输出结果:25
</script>

3、匿名函数

(1)函数表达式
概念:所谓函数表达式指的是将声明的函数赋值给一个变量,通过变量完成函数的调用和参数的传递,它也是JavaScript中另一种实现自定义函数的方式。
函数表达式与声明函数的区别:
在这里插入图片描述
(2)匿名函数
概念:匿名函数指的是没有函数名称的函数。
作用:可以有效的避免全局变量的污染以及函数名的冲突问题。
说明:既是函数表达式的另一种表示形式,又可通过函数声明的方式实现调用。

<body></body>

<script>
  // 方式1:函数表达式中省略函数名
  var fn = function (num1, num2) {
    return  num1 + num2;
  };
  fn(1, 2);
  // 方式2:自调用方式
  (function (num1, num2) {
    return  num1 + num2;
  })(2, 3);
  // 方式3:处理事件
  document.body.onclick  = function () {
    alert('Hi, everybody!');
  };
</script>

箭头函数
概念: ES6中引入了一种新的语法编写匿名函数,我们称之为箭头函数。
特点:一个箭头函数表达式的语法比一个函数表达式更短。
箭头函数

<script>
  // 用法1:标准语法
  (p1, p2, /* …, */ pN) => { statements }
  // 用法2:返回值
  (p1, p2, /* …, */ pN) => { return expression; }    // 或  (p1, p2, …, pN) => expression
  // 用法3:含有一个参数
  (singleParam) => { statements; }    // 或  singleParam => { statements; }
  // 用法4:无参箭头函数
  () => { statements; }    // 或   _ => { statements; }
</script>

<script>
  // 设置1个参数
  var fn1 = x => x + 2;
  console.log(fn1(4));           // 输出结果:6
  // 设置2个参数
  var fn2 = (x, y) => x + y;
  console.log(fn2(1, 2) );       // 输出结果:3
</script>

箭头函数中箭头“=>”不是操作符或者运算符,但是箭头函数相比普通的函数受操作符的优先级影响。

(3)回调函数

概念:所谓回调函数指的就是一个函数A作为参数传递给一个函数B,然后在B的函数体内调用函数A。此时,我们称函数A为回调函数。
提示:匿名函数常用作函数的参数传递,实现回调函数。
应用:函数体中某部分功能由调用者决定,此时可以使用回调函数。

<script>
  function cal(num1, num2, fn) {
    return fn(num1, num2);
  }
  console.log(cal(45, 55, function (a, b) {
    return a + b;
  }));
  console.log(cal(10, 20, function (a, b) {
    return a * b;
  }));
</script>

利用回调函数实现具体功能的方法
在这里插入图片描述

<script>
    //find() js 
    var arr=[1,2,3,4,5];
    function nums(num){
        return num>1;
    }
    // 数组内第一个大于1的值
    var res = arr.find( num => num>1);
    console.log(res);
</script>
<script>
    var arr=['a','b','c'];
    arr.map(function(value,index){
        console.log(value,index)
    })
</script>
<script>
  var arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];    // 待转置的数组
  var reverse = arr[1].map(function (col, i) {    // 利用i获取转置后数组元素的下标
    return arr.map(function (row) {               // 返回转置后新组合而成的数组元素
      return row[i];                              // 返回转置前数组元素的指定索引的元素
    });
  });
</script>
<script>
    let arrs = [1,2,3,4,5];
    let res = arrs.map(item => {
        return item*item
    });
    console.log(res);// [1,4,9,16,25]
</script>

<script>
    var arr1 = [12,23,45,13,33];
    // 判断arr1 数组元素 是否 都大于25
    arr1.forEach(item => {
        var res = true;
        if(item <25){
            res = false
        }
        return res
    });

    var bo = true;
    for(value in arr1){
        if(arr1[value]<25){
            bo=false
        }
    }
    console.log(bo);

    var flag = arr1.every(function(a){
        return a>25;//arr1数组内每个元素 都要大于25,才会返回true
    })
    console.log(flag);

    var flag = arr1.some(function(a){
        return a>25;//arr1数组内元素 有一个大于25,会返回true
    })
    console.log(flag);
</script>

4、函数的嵌套与递归

(1)函数嵌套与作用域链
什么是嵌套函数:是在一个函数内部存在另一个函数的声明。
特点:内层函数只能在外层函数作用域内执行,在内层函数执行的过程中,若需要引入某个变量,首先会在当前作用域中寻找,若未找到,则继续向上一层级的作用域中寻找,直到全局作用域,我们称这种链式的查询关系为作用域链。

<script>
    var i =26;
    function fn1(){
        var i = 24;
        function fn2(){
            function fn3(){
                console.log(i);//24
            }
            fn3();
        }
        fn2();
    }
    fn1();
</script>

在这里插入图片描述
(2)递归调用
概念:递归调用是函数嵌套调用中一种特殊的调用。它指的是一个函数在其函数体内调用自身的过程,这种函数称为递归函数。

<script>
    // 5的阶乘   5! = 5*4*3*2*1
    function fac(n){
        if(n==1){
            return 1;
        }
        return n * fac(n-1);
    }
    var n = prompt('求n的阶乘,请输入n的值:(n是大于等于1的正整数)')
    n=parseInt(n);
    if(isNaN(n)){
        alert('输入的n是不合法的')
    }else{
        alert(n+'的阶乘是:'+fac(n))
    }
</script>

阶乘
递归调用虽然在遍历维数不固定的多维数组时非常合适,但它占用的内存和资源比较多,同时难以实现和维护,因此在开发中要慎重使用函数的递归调用。

5、闭包函数

在JavaScript中,内嵌函数可以访问定义在外层函数中的所有变量和函数,并包括其外层函数能访问的所有变量和函数。但是在函数外部则不能访问函数的内部变量和嵌套函数。此时就可以使用“闭包”来实现。

闭包的常见创建方式:就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。

<script>
    // 闭包:常见创建方式-- 在一个函数内部创建另一个函数,
    // 通过另一个函数访问这个函数的局部变量。
    function fac(){
        var num =0;
        var c = function (){
            return ++num;
        }
        return c;
    }
    var count = fac();// 保存fac()返回的函数,此时count就是一个闭包

    console.log(count());
    console.log(count());
    console.log(count());
    console.log(count());
    console.log(count());
</script>

所谓“闭包”指的就是有权访问另一函数作用域内变量(局部变量)的函数。它最主要的用途是以下两点:
可以在函数外部读取函数内部的变量。
可以让变量的值始终保持在内存中。

由于闭包会使得函数中的变量一直被保存在内存中,内存消耗很大,所以闭包的滥用可能会降低程序的处理速度,造成内存消耗等问题。

案例:定义函数

<button id="btn">单击</button>
<div id="demo" style="display: none">这是一个惊喜!</div>
<script>
  function $(id) {    // 根据id获取元素对象
    return document.getElementById(id);
  }
  function show() {   // 显示id为demo的元素
    $('demo').style.display = 'block';
  }
  // 当按钮被点击的时候 显示下面的内容
  $('btn').onclick = show;
</script>

案例:网页计算器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>网页计算器</title>
</head>
<body>
    <p>整数1:<input id="num1" type="text"></p>
    <p>整数2:<input id="num2" type="text"></p>
    <p>
        <input type="button" value="相加" onclick="calc(add)">
        <input type="button" value="相减" onclick="calc(sub)">
        <input type="button" value="相乘" onclick="calc(mul)">
        <input type="button" value="相除" onclick="calc(div)">
    </p>
    <p>结果:<input id="res" type="text" readonly></p>
    <script>
        function calc(func){
            var res = document.getElementById('res');
            var num1 = parseInt(document.getElementById('num1').value);
            var num2 = parseInt(document.getElementById('num1').value);
            if(isNaN(num1)||isNaN(num2)){
                alert('请输入整数')
                return false;
            }
            res.value = func(num1,num2);
        }
        function add(num1,num2){
            return num1+num2;
        }
        function sub(num1,num2){
            return num1-num2;
        }
        function mul(num1,num2){
            return num1*num2;
        }
        function div(num1,num2){
            if(num2 === 0){
                alert('除数不能为0')
                return '';
            }
            return num1/num2;
        }
    </script>
</body>
</html>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值