首页 > 代码库 > js语言基础练习(二)---------------函数的基础知识

js语言基础练习(二)---------------函数的基础知识

函数概述、参数、返回值、函数名函数体和函数加载问题、函数声明、变量和作用域、隐式全局变量、变量声明提升。


1。函数的定义和使用

函数 ,具有一定功能的代码块 可以重复执行的代码块

 

函数不调用不执行  执行方法 fn()

函数定义 function fn(){}

 

预解析  function 和变量

函数调用可以在函数定义之前

 

<!DOCTYPE html>
<html>
<head>
    <title>函数的定义和使用</title>
</head>
<body>
<script type="text/javascript">

    fn_name();

    function fn_name(){
        alert(1);
    }
    // 定义函数

    function getSum(){
        var sum = 0;
        for (var i=1;i<=100;i++){
            sum+=i;
        }
        alert(sum);
    }

    fn1();  
    // 会输出1

    function fn1(){
        alert(1+1);
    }

    function fn1(){
        alert(1);
    }

    // a,b占位置用的,形参,形式上参与运算的值
    function fn2(a,b){
        alert(a+b);
    }

    fn2(4,4); 
    // 4,4实参,实际上参与运算的值 
    fn2(1,2);

    fn3();
    function fn3(a,b){
        alert(a+b);
        // NaN 

        alert(a);
        alert(b);
        // undefined,未定义,未赋值

        document.getElementById(a).title=1;
        // 未赋值,又进行强制操作,报错
    }

</script>

</body>
</html>

2.参数

参数 返回值 函数两大组成部分

函数的组成部分1:参数2返回值3功能

参数

需求1   1+1=?   Alert(1+1)

需求2    2+2=?   Alert(2+2)

需求3    4+4=?   Alert(4+4)

需求随时会改变,

可能修改运算的值而不是功能,可以设置参数,解决问题。

形参 形式上参与运算的值,占位置

实参 实际上参与运算的值

实参想参与运算必须要有形参占位置。

 

参数:增加函数功能性 如1+1  -》  a+b 功能强大

程序员交互性 

参数可拓展性

 

// a,b占位置用的,形参,形式上参与运算的值

       function fn2(a,b){

              alert(a+b);

       }

       fn2(4,4);

       // 4,4实参,实际上参与运算的值

 

函数名相同,后面的函数会覆盖前面的函数。函数名不能相同

 

3参数个数问题

如果形参个数与实参个数不匹配

一般情况下,不会让形参和实参不匹配

  1. 形参=实参  正常执行
  2. 实参》形参  正常执行,多余的实参无意义,函数不使用
  3. 实参《形参  看程序具体内容是否报错 NaN,undefined,报错

未给定实参,undefined

本身没有赋值,又对其进行强制操作,报错

fn3();

function fn3(a,b){

        alert(a+b);

        // NaN

 

        alert(a);

        alert(b);

        // undefined,未定义,未赋值

 

        document.getElementById(a).title=‘1‘;

        // 未赋值,又进行强制操作,报错

}

 

Js中没有方法重载,函数名相同(无关形参个数),后面的会覆盖前面的函数。

比如fn(a,b)

fn(a,b,c)

 

4.

  1. 返回值

什么是返回值:执行完毕函数以后,我们能给其他变量赋值。

 

把函数的值赋值给外面,使用return,否则返回值是undefined

 

返回值的作用:一般来说,函数通过运算出来的数都是一个半成品,需要二次加工,所有不能直接结束,需要在函数外部二次加工。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<script>
    //函数的组成分为:      1.参数。    2.返回值。    3.功能。

    //什么是返回值:执行完毕函数以后,我们能给其他变量赋值。
    //返回值干什么用的呢?一般来讲,函数通过运算出来的数都是一个半成品,需要二次加工。

    // 系统自带的函数,confirm等的返回值
   var bool1 = confirm("我们结婚吧?");
   console.log(bool1);
      // false,返回值是布尔值

   var bool2 = alert("我们结婚吧?");
   console.log(bool2);
        // undefined,返回值是undefined

   var bool3 = prompt("请输入:");
   console.log(bool3);
   // 返回值输入什么就是什么

    var aaa = fn();
    console.log(aaa);
    function fn(){
        var bbb = 111;
        //如果我们想把函数内部的值赋值为外部,必须使用return;
        //如果没有return或者只有return没有值,那么返回值都是undefined。
        return bbb;
    }

</script>
</body>
</html>

练习1:返回值必须执行函数才能得到,return可以退出函数

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <script>
        //函数的返回值必须要执行函数才能得到。

       //求和:
       var num = getSum()+1+1+1;
       alert(num);

       function getSum(){
           var sum = 0;
           for(var i=1;i<=100;i++){
               sum+=i;
           }
           return sum;
       }

        //需求:1+1=2;拓展这个算式
       var aaa = fn(1,1);
       alert(aaa);
       // 或者
       alert(fn(2,2));

       function fn(a,b){
           //规则中有几个变化的值,我们就定义几个变量。
           var sum = a+b;
           //外部要用哪个值,我们就返回哪个值。
           return sum;
       }

       demo();
       function demo(){
           console.log(1);
           console.log(2);
            // return可以切断函数。 后面的所有代码不再执行
            // break跳出这个循环。  continue跳出本次循环进入下一循环。
           return;
           console.log(3);
           console.log(4);
       }


    </script>
</body>
</html>

练习二:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<script>

    //(参数和返回值)
    //求圆的周长(long=2*pi*r)
   var long1 = getLong(0.5);
   console.log(long1);
   console.log(getLong(1));
   function getLong(r){
        // 通俗版
       var pi = 3.141592653;
       var l = 2*pi*r;
       return l;
   }

    //求圆的和面积(area = pi*r*r)
   var area1 = getArea(1);
   console.log(area1);
   function getArea(r){
       //通俗版
//        var pi = 3.14;
//        var a = pi*r*r;
//        return a;
       //精简版
//        var pi = Math.PI;
//        var a = pi*Math.pow(r,2);
//        return a;
       //最终版
       return Math.PI*Math.pow(r,2);
   }

    //求2个数中的最大值

   console.log(getMax(1,2));
   function getMax(num1,num2){
//        if(num1>num2){
//            return num1;
//        }else{
//            return num2;
//        }
       //return是可以切断函数的。
//        if(num1>num2){
//            return num1;
//        }
//        return num2;
       //三元运算
       return num1>num2?num1:num2;
   }

    //求3个数中的最大值
   console.log(getMaxThree(-1,0,3));
   function getMaxThree(a,b,c){
//        var d = a>b?a:b;
//        return d>c?d:c;
       //精简版
       return (a>b?a:b)>c?(a>b?a:b):c;
       //判断a和b
//        if(a>b){
//            //如果a大判断a和c
//            if(a>c){
//                return a;
//            }else{
//                return c;
//            }
//        }else{
//            //如果b打,判断b和c
//            if(b>c){
//                return b;
//            }else{
//                return c;
//            }
//        }
   }


    //求一组数中的最大值
   var arr = [-3,-2,-1,0,1,2,3];
   var maxValue = getArrMax(arr);
   console.log(maxValue);
   console.log(getArrMax(arr));

   function getArrMax(array){
       //用的必须是形参的数组中的第一项。
       var max = array[0];
       for(var i=1;i<array.length;i++){
           if(array[i]>max){
               max = array[i];
           }
       }
       return max;
   }

    //求一组数中的最小值
       var arr = [-3,-2,-1,0,1,2,3];
       var minValue = getArrMin(arr);
       console.log(minValue);
       console.log(getArrMin(arr));

   function getArrMin(aaa){
       //把数组中的第一位默认为,最小值。
       var min = aaa[0];
       for(var i=1;i<aaa.length;i++){
           //判断数组中的每一项,如果下雨min,那么把他赋值给min
           if(aaa[i]<min){
               min=aaa[i];
           }
       }
       //书写位置要注意,一定是这个for循环执行完毕之后再返回
       return min;
   }


    //翻转数组,返回一个新数组
    //用两种方法做,第一种创建心数组。第二种直接修改原数组。
   var arr1 = [1,2,3];
   var arr2 = reverse1(arr1);
   console.log(arr2);
   console.log(reverse1(arr1));
   //定义一个新数组,把老数组中的元素反向添加到新数组中
   function reverse1(array){
       var newArr = [];
       for(var i=array.length-1;i>=0;i--){
           newArr[newArr.length] = array[i];
       }
       return newArr;
   }

   var arr = [1,2,3];
   console.log(arr);
//    console.log(reverse2(arr));
   reverse2(arr);
   console.log(arr);
   //修改或者说翻转原数组,此方法没有返回值,所以只能打印原数组。
   function reverse2(array){
       for(var i=0;i<array.length/2;i++){
           var temp = array[i];
           array[i] = array[array.length-1-i];
           array[array.length-1-i] = temp;
       }
       return array;   //Array对象中的方法返回了一个数组。
   }


    //对数组排序,从小到大

//    var arr = [2,1,3,4];
    var arr = [4,3,2,1];
    console.log(bubble(arr));

    function bubble(array){
        //外循环控制轮数(元素-1)
        for(var i=0;i<array.length-1;i++){
            //开闭原则(标志,标识,旗帜)
            var flag = true;
            //内循环控制次数(元素-1)
            for(var j=0;j<array.length-1-i;j++){
                //判断符合标准就交换位置
                if(array[j]>array[j+1]){
                    var temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                    flag = false;
                }
            }
            if(flag){
                //此情况在数组是极限从大到小排列下,会出现问题。每一轮flag都是false,最终无返回值。
//                return array;
                break;
            }
        }
        //有了return执行完毕方法后,就可以用变量接收返回值!
        return array;
    }


</script>
</body>
</html>

练习3:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<script>
//    求阶乘
   console.log(getJC(10));

   function getJC(num){
       var sumJC = 1;
       for(var i=1;i<=num;i++){
           sumJC *= i;
       }
       return sumJC;
   }

//    求1!+2!+3!+....+n!(函数嵌套)
    //求阶乘的和

   console.log(getSumJC(4));

   function getSumJC(number){
       var sum = 0;
       for(var i=1;i<=number;i++){
           sum += getJC(i);//求阶乘
       }
       return sum;
   }


//    判断一个数是否是素数(质数)
    //思路:除了自身和1以外,不能被其他数整除。
    //注意点:
    //1.必须用for循环实现
    //2.判断是否是素数,所以她的返回值应该是true或者false。
    //3.如果num%i===0了,那么一定不是素数。只有出了1和自身以外所有的数都不能整除,那么才能说她是素数。

    console.log(isPrime(3));

//    function isPrime(num){
//        //除了自身和1以外,不能被其他数整除。
//        for(var i=2;i<num;i++){
//            if(num%i===0){
//                return false;
//            }
//        }
//        return true;
//    }

    //拓展1(了解)
//    function isPrime(num){
//        //开闭原则
//        var bool = true;
//        //除了自身和1以外,不能被其他数整除。
//        for(var i=2;i<num;i++){
//            if(num%i===0){
//                bool = false;
//            }
//        }
//        return bool;
//    }

    //拓展2
    function isPrime(num){
        //除了自身和1以外,不能被其他数整除。
        for(var i=2;i<=num/2;i++){
            if(num%i===0){
                return false;
            }
        }
        return true;
    }

    //拓展3
//    function isPrime(num){
//        //除了自身和1以外,不能被其他数整除。
//        //判断一个数是不是指数,只需要判断到他的平方根,超过平方根在判断,无意义。
//        //因为一个数是由两个数相称得到的,一个变大,另外一个必然变小,那么判断到这个数的平方根就已经是极限了,不必超过平方根
//        for(var i=2;i<=Math.sqrt(num);i++){
//            if(num%i===0){
//                return false;
//            }
//        }
//        return true;
//    }

</script>
</body>
</html>

 

5.函数名、函数体、函数加载

函数名,就等于整个函数。执行函数,就等于函数的功能+返回值。 js加载的时候只加载函数名,不加载函数体

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<script>
    //函数名,就等于整个函数。
    //执行函数,就等于函数的功能+返回值;
    // js加载的时候只加载函数名,不加载函数体

    //打印函数名,就等于打印整个函数。
    console.log(fn);
    //打印执行函数,就等于打印函数的返回值。
    console.log(fn());  //函数中包函数,先执行里面,后执行外面。


    function fn(){
        var arr = [1,3,3];
    }

</script>
</body>
</html>

6.函数的定义

三种定义方法

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<script>

//    //第一种定义方法最强大,定义完毕后,在哪里使用都可以,无位置限制。
//    fn1();
//    //后两种定义方法是有局限性的。(使用函数必须在定义函数之后)
//    fn2();
//    fn3();

    //第一种
    function fn1(){
        console.log("我是第一种定义方法!");
    }


    //第二种(匿名函数),函数不会被提前,使用必须在定义之后
    var fn2 = function (){
        console.log("我是第二种定义方法!");
    }


    //第三种
    var fn3 = new Function("console.log(‘我是第三种定义方法!‘)");

//    fn1();
//    fn2();
//    fn3();


</script>
</body>
</html>

7.变量和作用域

局部变量:只有局部能够访问到的变量

全局变量:在哪里都能访问的变量

隐式全局变量

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>


<script>

    //变量问题:根据作用范围,变量可以分为局部变量和全局变量。

    //局部变量:只有局部能够访问的变量。存在的时间比较短,执行完函数之后会被回收。
        //函数内部用var定义的变量。
    //全局变量:在哪里都能访问到的变量。
        //函数外部或者进入javascript之后立即定义的变量和函数内部不带有var的变量。

   var num3 = 333;
//全局变量

//    //函数加载的时候,只加载函数名,不加载函数体。
   function fn(){
       //局部变量,
       var num1 = 111;
       //全局变量(成员变量)
       num2 = 222;

       console.log(num3);
   }
//
   fn();
//    console.log(num1);  访问不到,因为num1是局部变量
   console.log(num2);  
   // 执行fn()之后num2才能访问到,因为函数加载时候只加载函数名,不加载函数体
   console.log(num3);


//    //块级作用域,js中没有。
//    {
//        var aaa = 1;
//    }

// 作用域指的是作用范围


    //隐式全局变量
    function fn(){
        //b和c都是隐式全局变量
        var a = b = c = 1;
        //e和f都是隐式全局变量(分号相当于换行)
        var d = 1;e =2;f=3;
        //g和i都不是隐式全局变量 ,g,h,i全是局部变量
        // ,相当于共用一个var
        var g = 1,h= 2,i=3;
    }

    fn();
    console.log(b);
    console.log(c);
    console.log(e);
    console.log(f);
//    console.log(a);
//    console.log(h);
//    console.log(i);



</script>
</body>
</html>

8.变量声明提升和预解析

预解析:js的解析器在页面加载的时候,首先检查页面上的语法错误。把变量声明提升起来。
变量值提升变量名,不提升变量值。而用function直接定义的方法是整体提升。
1.查看语法错误。
2.变量声明提升和函数整体提升(变量声明提升的时候,只提升变量名,不提升变量值)
3.函数范围内,照样适用。

 

函数就近原则

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

<script>
    
    // console.log(aaa);报错
   
    // console.log(aaa);
    // var aaa;  undefined 预解析

    // console.log(aaa);
    // var aaa=111;  undefined 预解析,但是变量值提升变量名,不提升变量值

    var aaa;
    console.log(aaa);
    aaa = 111;
    fn();

// 形参bbb相当于局部变量
    function fn(bbb){
        //
        //函数的就近原则。局部变量能解决的不会使用全局变量。

        // console.log(a);  报错
        // var a;
        // console.log(a);  undefined

        var aaa;
        //函数的就近原则。局部变量能解决的不会使用全局变量。这里的aaa是函数内部定义的局部变量

        console.log(aaa);   
        // undefined  变量声明提升在函数内部照样实用。
        aaa = 222;
    }

    function fn2(bbb){
        //两个函数中的局部变量不会相互影响。
        console.log(bbb);
    }

</script>

</body>
</html>

例子

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<script>

//    1、-----------------------------------

   var num = 10;
   fun();
   function fun(){
       //变量声明提升   只提升变量名,不提升变量值。var num;
       console.log(num);
       // undefined
       var num = 20;
   }
////    2、-----------------------------------
   var a = 18;
   f1();
   function f1(){
       var b=9;
       console.log(a);
       // undefined,就近原则,函数内部有a的定义,此时a是局部变量;根据变量声明提升,只提升变量名,不提升变量值。
       console.log(b);
       // 9
       var a = 123;
   }
////    3、-----------------------------------
            f2();
    console.log(cc);   
    // 9    输出顺序4 cc是全局变量,故有值
    console.log(bb);
    console.log(aa);
    // 报错,aa是局部变量,函数执行结束变量已经销毁,没有定义过
    function f2(){
        var aa = bb = cc = 9;
        // bb、cc隐式全局变量
        console.log(aa);   
        // 9   输出顺序1
        console.log(bb);
        // 9    输出顺序2
        console.log(cc);
        // 9    输出顺序3
    }


</script>
</body>
</html>

 

js语言基础练习(二)---------------函数的基础知识