• 第4天:function对象(案例:获取当前日期属于当年第几天、arguments对象、函数类型、参数、返回值、自身调用)


    获取当前日期输入当年第几天

      //输入,年月日,获取这个日期是这一年的第几天
        //年-月--日:20171月31日
        function getDay(year,month,day){
            //定义变量存储对应的天数
            var days=day
            //如果用户输入的是一月份,没有必要向后算天数,直接返回天数
            if(month==1){
                return days;
            }
            //代码执行到这里--用户输入的不是1月份
            //比如输入的是4月份23日---1,2,3,+23
            //定义一个数组,存储每个月的天数
            var months=[31,28,31,30,31,30,31,31,30,31,30,31];
            //获取到当前数的第三个月(索引:0,1,2)所以i<month-1
            for(var i=0;i<month-1;i++){
                //将输入的天数相加到一起
                days+=months[i]
            }
            //需要判断这个年份是不是闰年并且是否大于2
            if(isLeapYear(year)&&month>2){
                //那就在days加上1天
                days++;
            }
            return days;
        }
        //判断这个年份是不是闰年
        function isLeapYear(year){
            return year%4==0&&year%100!=0||year%400==0;
        }
    
       //2000年闰年31+29+2  62
        console.log(getDay(2000,3,2));//62

    arguments对象:arguments 是一个对应于传递给函数的参数的类数组对象。

    MDN:


    arguments对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments对象在函数中引用函数的参数。此对象包含传递给函数的每个参数,第一个参数在索引0处。例如,如果一个函数传递了三个参数,你可以以如下方式引用他们:

    arguments[0]
    arguments[1]
    arguments[2]

    参数也可以被设置:

    arguments[1] = 'new value';

    arguments对象不是一个 Array 。它类似于Array,但除了length属性和索引元素之外没有任何Array属性。例如,它没有 pop 方法。但是它可以被转换为一个真正的Array

    var args = Array.prototype.slice.call(arguments);
    var args = [].slice.call(arguments);
    
    // ES2015
    const args = Array.from(arguments);
    const args = [...arguments];

    对参数使用slice会阻止某些JavaScript引擎中的优化 (比如 V8 - 更多信息)。如果你关心性能,尝试通过遍历arguments对象来构造一个新的数组。另一种方法是使用被忽视的Array构造函数作为一个函数:

    var args = (arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments));

    如果调用的参数多于正式声明接受的参数,则可以使用arguments对象。这种技术对于可以传递可变数量的参数的函数很有用。使用 arguments.length来确定传递给函数参数的个数,然后使用arguments对象来处理每个参数。要确定函数签名中(输入)参数的数量,请使用Function.length属性。

    属性

    arguments.callee
    指向当前执行的函数。
    arguments.caller
    指向调用当前函数的函数。
    arguments.length
    指向传递给当前函数的参数数量。
    arguments[@@iterator]
    返回一个新的Array迭代器对象,该对象包含参数中每个索引的值。
    function f1(){
            //获取的是函数在调用的时候,传入了几个参数
            console.log(arguments.length)
            //使用arguments对象可以获取传入的每个参数的值
            console.log(arguments)
        }
        f1(10,20,30,40);//调用
        
        function f2(){
            var sum=0;
            arguments[1]=60;
            for(var i=0;i<arguments.length;i++){
                sum+=arguments[i];
            }
            return sum;
        }
        console.log(f2(10,20,30,40,50))

     函数其他定义方式:

    /*
        *命名函数:函数如果有名字就是命名函数
        *
        *匿名函数:函数如果没有名字,就是匿名函数
        *
        *函数的另一种定义方式
        *函数表达式
        *把一个函数给一个变量,此时形成了函数表达式
        *var 变量=匿名函数
        *var f1=function(){
        *
        *}
        *如果是函数表达式,那么此时前面的变量中存储的就是一个函数
        *而这个变量就相当于是一个函数,就可以直接加小括号调用了
        *
        *注意:
        *函数表达式后,要加分号;
        */
        //将匿名函数给了变量
        //函数表达式
        var f2= function (){
            console.log("匿名函数的调用")
        }
        f2();
        //函数表达式
        var f3= function (){
            console.log("我是一个匿名函数")
        }
        // var f1=function f4(){console.log("萌萌啊")};
        // f1();
        //函数调用自身没有写出来
      //  (function(){console.log("萌萌啊");})();

    函数数据类型

     function f1(){
            console.log("我是函数");
        }
        //如何获取某个变量的类型?typeof
        console.log(typeof f1)
        //函数是有数据类型,数据类型:function类型的

    函数作为参数传递时

    声明一个函数
     function f1(){
     console.log("这是一个函数")
     }
    
        function f2(fn){
            fn();//函数调用----说明fn变量中存储是一个函数
        }
        f2(f1)
    
     function sayHi(fn){
     console.log("函数作为参数木有调用前")
     fn();//当前fn变量存储的为一个函数
     }
     function mengSay(){
     console.log("努力啊!小伙子");
     }
     sayHi(mengSay)
    
    
     //函数作为返回值使用
        function fn(){
            console.log("fn函数调用了");
            return function (){
                console.log("我是一个匿名函数");
            }
        }
        //fn()//调用
        var jieShou=fn();//将fn函数赋值给变量jieShou
        jieShou();//实际调用函数

    js作用域

    *全局变量:声明变量是使用var声明的,那么这个变量就是全局变量,全局变量
    *可以在页面的任何位置使用
    *除了函数以外,其他的任何位置定义的变量都是全局变量
    *局部变量:在函数内部定义的变量,是局部变量,外面不可以使用
    *全局变量如果页面不关闭,那么就不会释放,就会占空间,消耗内存
    *
    *
    *
    *块级作用:一对大括号就可以看成是一块,在这块区域中定义的变量,只能在这个
    *区域中使用,但是js中在这个块级作用域中定义的变量,外面也可以使用
    *说明:js中没有块级作用域,只有函数除外
    *
    *隐式全局访问:声明的变量没有var,就叫隐式变量
    *全局变量是不能被删除,隐式全局变量是可以被删除
    *定义变量使用var是不会被删除的,没有var是可以删除的
     if(true){
            var num=10;
        }
        console.log(num);//可以使用
        for(var i=1;i<100;i++){
            var number=100;
        }
        console.log(number);//可以使用
        function f1(){
            var ceShi=1000;
        }
       // console.log(ceShi)//不能使用
        var num1=10;
        num2=20;
        delete num1;//不可以删除
        delete num2;//可以删除
        console.log(typeof num1);
        console.log(num1+10);
        console.log(typeof num2);

    作用域链:

    //js作用域链
        //从函数的作用域内开始,如果当前不存在变量,逐层向上找
        //如f1函数中 f3函数如果找不到num;就会向上f2函数找num.....逐层
        
         var num=10;
         function f1(){
             var num=20;
             function f2(){
                 var num=30;
                 function f3(){
                     var num=40;
                     console.log(num)
                 }
             }
         }

    预解析

      //预解析:提前解析代码
        console.log(num);//undefined
        //把变量的声明提前了
        var num=10;
    预解析中,变量的提升,只会在当前作用域中提升,提前到当前作用域的最上面
    函数中的变量只会提前到函数的作用域中的最前面,不会出去
    预解析会分段,预解析的时候不同的script标签,同名的函数不会冲突
    function f1(){
            console.log(num);//undefined;
            var num=10;        
        }
        f1();
        console.log(num);//not defined 没有定义

    运行结果:

    预解析会将变量声明提前 函数声明提前

         var a=25;
         function add(){
    // var a; alert(a);
    //undefined 预解析会将变量声明提前 函数声明提前 即 var a; var a=10; } add();
    console.log(a)//25 第一个a是全局变量 可以访问 函数中的a作用域只在add函数中,不可以访问

    预解析会将变量a提前声明,同时也将函数a()提前声明,即a不会等于undefined,因为a重名,所以已经被函数a()覆盖(暂时这样理解)

     console.log(a); //  function a(){
                        //     console.log("aaaaa");
                        //  }
        function a(){
            console.log("aaaaa");
        }
        var a=1;
        console.log(a);//1

    预解析会先将变量提前声明,再到函数提前声明,根据作用域链(先作用域内查找变量再逐层向上)——————script标签内的变量先提前声明——————>再到函数提前声明————>函数内作用域:变量也会提前声明——————>一步一步结果如下:

     var a=10;
        //预解析
        // var a; a=10
        // function f1(){
        //     var b; var a;b=9;
        //     var b=9;
        //     console.log(a)//因为预解析
        //     console.log(b)
        //    var  a="123";
        // }
        f1()
        function f1(){
            var b=9;
            console.log(a)//因为预解析
            console.log(b)
           var  a="123";
        }
    
        f1();

    案例分析:局部变量和隐式变量

    function f1(){
            var a=b=c=9;
            /*
            var a;//函数内声明的 局部变量
            a=9;
            b=9;//隐式变量
            c=9;//隐式变量
            */
            console.log(a);//9
            console.log(b);//9
            console.log(c);//9
        }
        f1();
            console.log(a);// not definde 所以报错
            console.log(b);//9
            console.log(c);//9

     

    //var f1;
        f1();//不能调用
        var f1=function (){//因为f1是变量 声明会提前
            console.log(a);
            var a=10;
        }
  • 相关阅读:
    openCV中cvSnakeImage()函数代码分析
    程序所有重构,升级的目标(备注,更新)
    基础总结篇之中的一个:Activity生命周期
    Tomcat全攻略
    VRRP协议具体解释
    二叉树三种遍历(递归以及非递归实现)
    AssertValid函数学习
    java定时器的使用(Timer)
    循环队列
    使用Heartbeat实现双机热备
  • 原文地址:https://www.cnblogs.com/shapaozi/p/10211776.html
Copyright © 2020-2023  润新知