掌握JavaScript函数,让你的代码更加优雅-灵析社区

Ned

函数的概述

  1. 什么是函数?
将一个(反复)使用的功能,封装成一个独立的模块,这个模块叫做函数。

2. 好处

使程序可控 一次封装,无限次使用(增加代码的复用度)

3. 函数的类型

Function

4. 函数的分类

内置函数(库函数、系统函数) 自定义函数

函数的声明

  1. 语句定义法(声明式函数): 可以任意位置调用!
function 函数名([参数]){
    //功能
}

2. 表达式定义法(赋值式函数):只能先声明,后使用!

var 变量名 = function([参数]){
    //功能
}
    <script>
        //声明式函数
        function fn1(){
            // 输出1~100中的所有素数(素数:只能被1和它本身整除的数)
            // 1~100  i = 1;i < 101;i ++
            //  j = 2;j <= 本身; j ++
            var str = ''; //放置所有素数的变量
            for(var i = 1;i < 101;i ++){
                for(var j = 2;j <= i;j ++){
                    if(i % j === 0){
                        break;
                    }
                }
                if(i === j){
                    str += i + ' ';
                }
            }
            document.write(str);
        }
        fn1();
        document.write('<br>');
        fn1();
        document.write('<br>');
        fn1();
    </script>

函数的调用

  1. 一般调用 :函数名([参数])

函数的参数

  1. 形式参数(形参) :声明函数时使用的参数
  2. 实际参数(实参) :调用函数时使用的参数
    <script>
 
        //声明函数
        function fn(m,n){  //形参(形式参数):用于接收实参的值,必须是变量
            // 输出m行n列的8
            //m 行: 从第一行开始,最m行结束,步长
            var str = '';
            for(var row = 1;row <= m;row ++){
                //n 列: 从第一列开始,最n列结束,步长
                for(var col = 1;col <= n;col ++){
                    str += 8;
                }
                str += '\n';
            }
            console.log(str);
            console.log(m,n);
        }
        //  m = 8
        var a = parseInt(prompt('请输入行数:'));
        var  b = parseInt(prompt('请输入列数:'));
        fn(a,b);  //实参(实际参数):给形参传递的数据,可以是常量 ,变量,表达式
    </script>
如果实参的数量少于形参的数量时,多余的形参值为undefined 如果实参的数量多于形参的数量时,多余的实参忽略。

函数的返回值

  1. return
  • 将函数中处理后的结果返回到调用该函数的地方。
  • 退出函数

2. 比如 1 + 2 是一个表达式,那么 这个表达式的结果就是 3

console.log(1 + 2) // 3
​
function fn() {
  // 执行代码
}
​
// fn() 也是一个表达式,这个表达式就没有结果出现
console.log(fn()) // undefined
  <script>
        //返回值:将函数中处理的功能后,得到的结果返回到调用这个函数的地方。
        function fn(){
            // 输出一元钱的兑换方案(1角2角5角)
 
                1角:var one = 0;one < 11;one ++
                2角:var two = 0;two < 6;two ++
                5角:var five = 0;five < 3;five ++
                if(1 * one + 2 * two + 5 * five === 10){
 
                }
 
            var str = '';
            for(var one = 0;one < 11;one ++){
                for(var two = 0;two < 6;two ++){
                    for(var five = 0;five < 3;five ++){
                        if(1 * one + 2 * two + 5 * five === 10){
                            str += one + ' 张壹角 ' + two + ' 张贰角 ' + five + ' 张伍角\n';
                        }
                    }
                }
            }
            console.log(str);
            return str; //将处理后的结果返回到调用这个函数的地方。
            退出函数了
            alert('瞧瞧');
        }
 
        var result = fn(); //调用fn()的函数,将返回的结果str赋值给result变量
        console.log(result);
 
        console.log(fn());
 
        fn();
 
        console.log(fn());
    </script>

函数作用域

JavaScript中有全局作用域和函数作用域两种作用域,函数作用域只在函数内部有效。在函数内定义的变量和函数只能在该函数内部访问,不能在函数外部访问。以下是函数作用域的示例:

function greet(name) {
  const message = 'Hello, ' + name + '!';
  console.log(message);
}
 
greet('Alice'); // 输出 Hello, Alice!
console.log(message); // 抛出错误:message未定义

闭包

闭包是指在一个函数中定义了另一个函数,并且内部函数可以访问外部函数的变量。在JavaScript中,函数可以嵌套定义,内部函数可以访问外部函数的变量,从而形成闭包。以下是闭包的示例:

function add(a) {
  return function(b) {
    return a + b;
  }
}
 
const add2 = add(2);
console.log(add2(3)); // 输出 5

在上面的示例中,add() 函数返回一个匿名函数,这个匿名函数可以访问 add() 函数的参数 a。定义 add2 变量时,将 add(2) 赋值给它,此时 add2 变量就成为了一个新的函数,这个函数可以接收一个参数并返回参数与 a 的和。

回调函数

回调函数是指将函数作为参数传递给另一个函数,并在另一个函数中调用它。在JavaScript中,回调函数常用于异步编程中,在异步操作完成后执行回调函数。以下是回调函数的示例:

function add(a, b, callback) {
  const result = a + b;
  setTimeout(function() {
    callback(result);
  }, 1000);
}
 
add(2, 3, function(result) {
  console.log(result); // 输出 5
});

匿名函数

除了通过function关键字定义函数外,还可以使用匿名函数,例如:

var add = function(a, b) {
  return a + b;
};
var result = add(3, 4); // 结果为7

函数作为参数

在JavaScript中,函数可以作为参数传递给其他函数,例如:

function operate(a, b, operation) {
  return operation(a, b);
}
var sum = operate(5, 3, function(x, y) { return x + y; }); // 结果为8

案例

  • 使用函数求三个数中的最大数
 <script>
        //使用函数求三个数中的最大数
            比较 - 选择语句
            1. 先求出前两个数中的最大值  一个条件,两个结果(双分支语句)
            2. 再拿前两个数中的最大值与剩下的下数进行比较,一个条件,一个结果(单分支)
 
        //求三个数中最大值的函数
        function fnMax(a,b,c){
            //求最大值
            var max = a > b ? a : b;
            //与剩下的一个数进行比较
            if(c > max){
                max = c;
            }
            return max;
        }
 
        // alert(fnMax(4,2,5));
 
            编写函数iseven,其功能为判断一个整数是否为偶数,若是偶数,返回1,否则返回0,在程序中调用此函数,对输入的一个整数进行判断,若是偶数,输出even,否则输出odd
        //封装一个判断奇偶的函数,将结果返回
        function iseven(n){
            return n % 2 ? 0 : 1;
        }
 
        // 输入的一个整数
        var i = parseInt(prompt('请输入一个整数:'));
        //声明一个变量,接收函数的返回值
        var result = iseven(i); 
        //根据返回值,判断输出even还是odd
        alert(result === 1 ? 'even' : 'odd');
    </script>
  • 编程求x的阶乘和y的阶乘的和,要求设计一个fac(n)函数求正整数n的阶乘
 <script>
        编程求x的阶乘和y的阶乘的和,要求设计一个fac(n)函数求正整数n的阶乘
        x的阶乘
        y的阶乘
        和
        
        //封装一个求正整数n的阶乘
        function fac(n){
            for(var i = 1,result = 1;i <= n;i ++){
                result *= i;
            }
            return result;
        }
        //准备两个变量,接收两个整数
        var x = parseInt(prompt('请输入一个整数:'));
        var y = parseInt(prompt('请输入一个整数:'));
        //求和
        var sum = fac(x) + fac(y);
        alert(sum);
    </script>
  • 利用函数实现面积计算器(计算长方形、三角形、圆形的面积)。Math.PI
   <script>
        利用函数实现面积计算器(计算长方形、三角形、圆形的面积)。Math.PI
        1. 长方形: 长 * 宽
        2. 三角形:底 * 高 / 2
        3. 圆形:  Math.PI * r * r
        //封装一个长方形面积的函数
        function rectangle(long,width){
            return long * width;
        }
        //封装一个三角形面积的函数
        function triangle(bottom,height){
            return (bottom * height / 2).toFixed(2);
        }
        //封装一个圆形面积的函数
        function circle(r){
            return (Math.PI * r * r).toFixed(2);
        }
        //封装一个计算器的函数
        function calculator(){
            //设计一个无限循环
            while(1){
                //提示用户输入功能
                var n = parseInt(prompt('0: 退出 1: 长方形 2: 三角形 3: 圆形\n请选择:'));
                //判断
                switch(n){
                    case 1 : 
                        //输入长
                        var long = parseInt(prompt('请输入长方形的长:'));
                        //输入宽
                        var width = parseInt(prompt('请输入长方形的宽:'));
                        alert('长方形的面积是:' + rectangle(long,width));
                        break;
                    case 2 : 
                        //输入底
                        var bottom = parseInt(prompt('请输入三角形的底:'));
                        var height = parseInt(prompt('请输入三角形的高:'));
                        alert('三角形的面积是:' + triangle(bottom,height));
                        break;
                    case 3 : 
                        //输入半径
                        var r = parseInt(prompt('请输入圆形的半径:'));
                        alert('圆形的面积是:' + circle(r));
                        break;
                    case  0 : return; //退出函数
                    default : alert('其它图形的面积尚未开放,敬请期待!');
                }
            }
        }
        calculator();
    </script>
  • 计算s=2^2!+3^2!
   <script>
            计算s=2^2!+3^2!
            2^2  求2的平方  2 * 2
            阶乘
            和
        //1. 求平方函数
        function square(n){
            return n * n;
        }
        //2. 阶乘
        function fac(n){
            for(var i = 1,result = 1;i <= n;i ++){
                result *= i;
            }
            return result;
        }
        //3. 和 
        function sum(){
            return fac(square(2)) + fac(square(3));
        }
        alert(sum());
    </script>

递归函数

自己调用自己的过程。
  1. 本质:循环
  2. 三要素:从哪里开始,到哪里结束、步长
建议在循环嵌套不确定层数时,使用递归函数。
// 下面这个代码就是一个最简单的递归函数
// 在函数内部调用了自己,函数一执行,就调用自己一次,在调用再执行,循环往复,没有止尽
function fn() {
  fn()
}
fn()

案例

  • 1 + 2 + 3 + …… + 100的和
  <script>
        //递归:实现循环 (三要素)
        //求 1 + 2 + 3 + …… + n 的和
        function fnSum(n){  //从哪里开始  5  4   3  2  1
            //到哪里结束,退出循环的条件
            if( n === 1){
                return 1;
            }else{
                return n + fnSum(n - 1); //步长
                //    5  + 4 + 3 + 2 + 1
            }
        }
        console.log(fnSum(5));
 
        // 求 n!
        function fnFac(n){
            if(n === 1){
                return 1;
            }else {
                return n * fnFac(n - 1);
            }
        }
        console.log(fnFac(5));
    </script>
  • 斐波那契数列
  <script>
        //斐波那契数列: 下一个数是前两个数的和
        //  1   1   2   3   5   8   13   21   34   55
        function fib(n){ //循环初值,代表的是第几个斐波那契数字
            //循环条件(退出条件)
            if(n == 1 || n == 2){
                return 1;
            }else{
                return fib(n - 1) + fib(n - 2);
            }
        }
        // alert(fib(10));
        for(var i = 1;i < 21;i ++){
            console.log(fib(i));
        }
    </script>
  • 输出10个Hello world
  <script>
        //输出10个Hello world
        function print(n){
            if(n === 0){
                
                return;
            }else{
                console.log('helloworld');
                print(n - 1);
            }
        }
        print(5);
    </script>

作用域及作用域链详解

    <script>
        //1. 作用域:JS代码作用的范围
        //2. 一旦进入作用域,浏览器就会启动JS解析器
 
            一、寻找东西? (var  function  形参)
                a = 1
                fn = function fn(){alert(2)}
            //1. 当找到var 或者 形参 时,取后面的名字存储在内存中,并给它初始化一个值undefined
            //2. 当找到function时,取函数名存储在内存中,并将整个函数块赋值给这个函数名.
 
            二、逐行解读代码 (遇到函数声明,则直接跳过)
                1. 执行表达式
                2. 函数调用
        alert(a); //undefined
        var a = 1;
        alert(a); //1
        function fn(){
            alert(2);
        }
        alert(a); //1
    </script>
 <script>
        //1. 作用域:JS代码作用的范围
        //2. 一旦进入作用域,浏览器就会启动JS解析器
 
            一、预解析(寻找东西?) (var  function  形参)
                
                
                a = 3
 
            //1. 当找到var 或者 形参 时,取后面的名字存储在内存中,并给它初始化一个值undefined
            //2. 当找到function时,取函数名存储在内存中,并将整个函数块赋值给这个函数名.
            //3. 当变量名与函数名相同时,丢变量、保函数
 
            二、逐行解读代码 (遇到函数声明,则直接跳过)
                1. 执行表达式
                2. 函数调用
        
        alert(a);    //function a(){alert(4)}
        var a = 1;
        alert(a); //1
        function a(){
            alert(2);
        }
        alert(a);  //1
        var a = 3;
        alert(a); //3
        function a(){
            alert(4);
        }
        alert(a);  //3
    </script>
   <script>
        //1. 作用域:JS代码作用的范围
        //2. 一旦进入作用域,浏览器就会启动JS解析器
            一、预解析(寻找东西?) (var  function  形参)
                fn = function fn(){alert(2)}
                a = 1
                
 
            //1. 当找到var 或者 形参 时,取后面的名字存储在内存中,并给它初始化一个值undefined
            //2. 当找到function时,取函数名存储在内存中,并将整个函数块赋值给这个函数名.
            //3. 当变量名与函数名相同时,丢变量、保函数
            //4. 当有多个script标签时,从上到下依次解决每一个script标签,所以建议大家 《将所有声明的语句放到第一个script标签中》
 
            二、逐行解读代码 (遇到函数声明,则直接跳过)
                1. 执行表达式
                2. 函数调用
        
        alert(a);    //报错
        function fn(){
            alert(2);
        }
    </script>
    <script>
        var a = 1;
        fn(); //2
    </script>
   <script>
        //1. 作用域:JS代码作用的范围
        //2. 一旦进入作用域,浏览器就会启动JS解析器(一、预 解析 二、逐行解读代码)
        //3. var 声明在script作用域的变量,称为全局变量,作用范围是整个页面,生存周期在页面开始运行时开启空间,到页面退出时释放内存空间。同时也是window对象的属性。如果var声明的变量或形参在函数中时,称为局部变量,作用范围仅限于当前函数中,生存周期在函数调用时开启空间,到函数调用结束后,释放内存空间。
        //4. 作用域链:从一个作用域中未寻找到内容,会向父级作用域中查找,这个向上查找的过程,称为作用域链。
            一、预解析(寻找东西?) (var  function  形参)
                a = 2
                fn = function(){}
 
            //1. 当找到var 或者 形参 时,取后面的名字存储在内存中,并给它初始化一个值undefined
            //2. 当找到function时,取函数名存储在内存中,并将整个函数块赋值给这个函数名.
            //3. 当变量名与函数名相同时,丢变量、保函数
            //4. 当有多个script标签时,从上到下依次解决每一个script标签,所以建议大家 《将所有声明的语句放到第一个script标签中》
 
            二、逐行解读代码 (遇到函数声明,则直接跳过)
                1. 执行表达式
                2. 函数调用 (函数也是一个作用域)
                    一、预解析
 
                    二、逐行解读代码
                        1. 执行表达式
                        2. 函数调用
        
        alert(a); //undefined
        var a = 1;
        alert(a);  //1
        function fn(){
            alert(a);  //1
            a = 2;
            alert(a);  //2
        }
        fn();
        alert(a);  //2
    </script>
 <script>
        //1. 作用域:JS代码作用的范围
        //2. 一旦进入作用域,浏览器就会启动JS解析器(一、预 解析 二、逐行解读代码)
        //3. var 声明在script作用域的变量,称为全局变量,作用范围是整个页面,生存周期在页面开始运行时开启空间,到页面退出时释放内存空间。同时也是window对象的属性。如果var声明的变量或形参在函数中时,称为局部变量,作用范围仅限于当前函数中,生存周期在函数调用时开启空间,到函数调用结束后,释放内存空间。
        //4. 作用域链:从一个作用域中未寻找到内容,会向父级作用域中查找,这个向上查找的过程,称为作用域链。
            一、预解析(寻找东西?) (var  function  形参)
               a = 1
                fn = function(){}
            //1. 当找到var 或者 形参 时,取后面的名字存储在内存中,并给它初始化一个值undefined
            //2. 当找到function时,取函数名存储在内存中,并将整个函数块赋值给这个函数名.
            //3. 当变量名与函数名相同时,丢变量、保函数
            //4. 当有多个script标签时,从上到下依次解决每一个script标签,所以建议大家 《将所有声明的语句放到第一个script标签中》
 
            二、逐行解读代码 (遇到函数声明,则直接跳过)
                1. 执行表达式
                2. 函数调用 (函数也是一个作用域)
                    一、预解析
                        a = 2
                    二、逐行解读代码
                        1. 执行表达式
                        2. 函数调用
        
        alert(a); //undefined
        var a = 1;
        alert(a);  //1
        function fn(){
            alert(a);  //undefined
            var a = 2;
            alert(a);  //2
        }
        fn();
        alert(a);  //1
    </script>
   <script>
        //1. 作用域:JS代码作用的范围
        //2. 一旦进入作用域,浏览器就会启动JS解析器(一、预 解析 二、逐行解读代码)
        //3. var 声明在script作用域的变量,称为全局变量,作用范围是整个页面,生存周期在页面开始运行时开启空间,到页面退出时释放内存空间。同时也是window对象的属性。如果var声明的变量或形参在函数中时,称为局部变量,作用范围仅限于当前函数中,生存周期在函数调用时开启空间,到函数调用结束后,释放内存空间。
        //4. 作用域链:从一个作用域中未寻找到内容,会向父级作用域中查找,这个向上查找的过程,称为作用域链。
            一、预解析(寻找东西?) (var  function  形参)
                a = 1
                fn = function(){}
            //1. 当找到var 或者 形参 时,取后面的名字存储在内存中,并给它初始化一个值undefined
            //2. 当找到function时,取函数名存储在内存中,并将整个函数块赋值给这个函数名.
            //3. 当变量名与函数名相同时,丢变量、保函数
            //4. 当有多个script标签时,从上到下依次解决每一个script标签,所以建议大家 《将所有声明的语句放到第一个script标签中》
 
            二、逐行解读代码 (遇到函数声明,则直接跳过)
                1. 执行表达式
                2. 函数调用 (函数也是一个作用域)
                    一、预解析
                        a = 2
                    二、逐行解读代码
                        1. 执行表达式
                        2. 函数调用
        
       
        var a = 1;
        alert(a);  //1
        function fn(a){  //形参
            alert(a);  //undefined
            a = 2;
            alert(a);  //2
        }
        fn();
        alert(a);  //1
    </script>
  <script>
        //1. 作用域:JS代码作用的范围
        //2. 一旦进入作用域,浏览器就会启动JS解析器(一、预 解析 二、逐行解读代码)
        //3. var 声明在script作用域的变量,称为全局变量,作用范围是整个页面,生存周期在页面开始运行时开启空间,到页面退出时释放内存空间。同时也是window对象的属性。如果var声明的变量或形参在函数中时,称为局部变量,作用范围仅限于当前函数中,生存周期在函数调用时开启空间,到函数调用结束后,释放内存空间。
        //4. 作用域链:从一个作用域中未寻找到内容,会向父级作用域中查找,这个向上查找的过程,称为作用域链。
            一、预解析(寻找东西?) (var  function  形参)
                a = 1
                fn = function(){}
            //1. 当找到var 或者 形参 时,取后面的名字存储在内存中,并给它初始化一个值undefined
            //2. 当找到function时,取函数名存储在内存中,并将整个函数块赋值给这个函数名.
            //3. 当变量名与函数名相同时,丢变量、保函数
            //4. 当有多个script标签时,从上到下依次解决每一个script标签,所以建议大家 《将所有声明的语句放到第一个script标签中》
 
            二、逐行解读代码 (遇到函数声明,则直接跳过)
                1. 执行表达式
                2. 函数调用 (函数也是一个作用域)
                    一、预解析
                        a = 2
                    二、逐行解读代码
                        1. 执行表达式
                        2. 函数调用
        
       
        var a = 1;
        alert(a);  //1
        function fn(a){  //形参  a = 1
            alert(a);  //1
            a = 2;
            alert(a);  //2
        }
        fn(a);  //实参
        alert(a);  //1
    </script>
    <script>
        //1. 作用域:JS代码作用的范围
        //2. 一旦进入作用域,浏览器就会启动JS解析器(一、预 解析 二、逐行解读代码)
        //3. var 声明在script作用域的变量,称为全局变量,作用范围是整个页面,生存周期在页面开始运行时开启空间,到页面退出时释放内存空间。同时也是window对象的属性。如果var声明的变量或形参在函数中时,称为局部变量,作用范围仅限于当前函数中,生存周期在函数调用时开启空间,到函数调用结束后,释放内存空间。
        //4. 作用域链:从一个作用域中未寻找到内容,会向父级作用域中查找,这个向上查找的过程,称为作用域链。
            一、预解析(寻找东西?) (var  function  形参)
                a = 2
                fn = function(){}
            //1. 当找到var 或者 形参 时,取后面的名字存储在内存中,并给它初始化一个值undefined
            //2. 当找到function时,取函数名存储在内存中,并将整个函数块赋值给这个函数名.
            //3. 当变量名与函数名相同时,丢变量、保函数
            //4. 当有多个script标签时,从上到下依次解决每一个script标签,所以建议大家 《将所有声明的语句放到第一个script标签中》
            //5. 如果在所有的作用域中都没有找到这个变量,则会在全局作用域中因为赋值号的原因,自动生成这个变量。
            二、逐行解读代码 (遇到函数声明,则直接跳过)
                1. 执行表达式
                2. 函数调用 (函数也是一个作用域)
                    一、预解析
                        
                    二、逐行解读代码
                        1. 执行表达式
                        2. 函数调用
 
        
        function fn(){  
            a = 2;
            alert(a);  //2
        }
        fn();  
        alert(a);  //2
    </script>


阅读量:550

点赞量:0

收藏量:0