zoukankan      html  css  js  c++  java
  • JS函数深入

    函数的本质是对象

    三种定义方式

    1、  字面量=function声明

                function add() {
                    // body...
                }
                add();

    2、  var赋值表达式

                var add = function (argument) {
                    // body...
                };
                add();
                var add = function fn(argument) {
                    // body...
                    fn();
                    add();
                };
                add();
                fn();//会报错,只能在函数体内调用

    3、  构造函数

        var add = new Function('num1', 'num2', 'return num1 + num2;');
                add();

    三种定义方式区别:

    字面量=function声明:预加载时add=function

        console.log(add());
        function add() {
            return 1;
    }

    var赋值表达式:预加载时add=undefined

        console.log(add());
        var add = function () {
            return 1;
    };

    构造函数:少用


    杂七杂八的知识点:

    JS中没有块级作用域,所以不会在if中发生预解析,在外部预解析的时候,if中声明的所有函数都会被提前,所以无法达到按需定义的目的。

    内部函数可以访问外部函数的变量(作用域链的机制)


    案例:写出一个加法(add)函数,并在其内部定义一个函数(isNumber),用来判断add的参数是否可以转化为数字类型进行相加,

    如果可以,就在页面中输出结果;

    如果不能就退出add,给出提示“请传入数字类型的参数”

    function add(num1,num2){
        if(isNaN(num1) || isNaN(num2)){
            alert('请传入数字类型的参数');
            return;
        }else{
            return parseInt(num1)+parseInt(num2);
        }
    }

    var num1=prompt('请输入数字1');

    var num2=prompt('请输入数字2');

    alert(add(num1,num2));

    案例:匿名函数也是函数,当它自执行的时候会创建函数作用域,它里面的变量和函数都是局部的,当匿名函数执行完毕后会被销毁。所以我们在外面访问不到add

        function () {
            function add(num1,num2){
                return num1+num2;
            }
        }();
        document.write(add(1,2));//报错

    匿名函数自执行方式:

        var add = function () {
            console.log(1);
        }();
    
        (function () {
            console.log(1);
        })();
    
        !+-~function () {
            console.log(1);
        }();

    递归调用:递归调用就是自己调用自己,但切记一定要有终止条件,否则函数将无限递归下去

        function factorial(num) {
            if (num <= 1) return 1;
            return num * factorial(num - 1);
            // return 5 * 4! = 5 * 4 * 3! =... 5 * 4 * 1!
        }
        console.log(factorial(5));

    方法的调用:

        document.onclick = function () {
            console.log('你点击了文档!');
        };
        document.onclick();
        var operation = {
            add: function (num1, num2) {
                return num1 + num2;
            },
            subtract: function (num1, num2) {
                return num1 - num2;
            },
            '@': function () {
                console.log('@');
            },
            key: function () {
                // body...
            }
        };
        console.log(operation.add(1, 2));
        console.log(operation['@'](1, 2)); //@符比较特别
        var key = 'add';
        console.log(operation[key](1, 2));

    链式调用

        var operation = {
            add: function (num1, num2) {
                console.log(num1 + num2);
                return this;
            },
            subtract: function (num1, num2) {
                console.log(num1 - num2);
                return this;
            },
            '@': function () {
                console.log('@');
            },
            key: function () {
                // body...
            }
        };
        operation.add(1, 2).subtract(2, 1);

    间接调用:

    对象没有call和apply方法,只有函数有

    call和apply的唯一区别就在它们传参的方式上

    apply可以将数组和类数组一次性的传递进函数中,call只能一个一个的传;

        var name = 'xm';
        var person = {};
        person.name = 'xh';
        person.getName = function () {
            return this.name;
        };
        console.log(person.getName()); //this指向person
        console.log(person.getName.call(window)); //this指向window
        console.log(person.getName.apply(window)); //this指向window
    
        function add(num1, num2) {
            return num1 + num2;
        }
        console.log(add(1, 2));
        var datas = [1, 2];
        console.log(add.call(window, 1, 2));
        console.log(add.apply(window, datas)); //apply(ele,[])

    输出:'xm', [object Object]

    person()就是普通函数的调用,返回值是return后面的内容:'xm' ; new person()是将person作为构造函数调用,返回的永远是对象 ; document.write没法输出对象,它会尝试着将其转换成字符串输出

     

    输出:undefined

    call可以改变函数中this的指向,这里在调用方法的时候将其this改为了window,所以this.value就变成了window.value,而window.value没有定义过,所以为undefined


    函数的参数:

    function add() {
        if (arguments.length == 0) return;
        var sum = 0;
        for (var i = 0; i < arguments.length; i++) {
            sum += arguments[i];
        }
        return sum;
    }
    console.log(add());
    console.log(add(1, 2, 3, 4, 5));

    arguments

    类数组,实质是类

    function fn(name) {
        arguments[0] = '';
        console.log(name);
    }
    fn('xm');//没有输出

    arguments.callee 指代函数本身,多用于递归

    计算阶乘方法一:

    function factorial(num) {
        if (num <= 1) return 1;
        return num * factorial(num - 1);
    }
    console.log(factorial(5));

    计算阶乘方法二:

    function factorial(num) {
        if (num <= 1) return 1;
        return num * arguments.callee(num - 1);
    }
    console.log(jiecheng(5));

    计算阶乘方法三:

    var jicheng = function fn(num) {
        if (num <= 1) return 1;
        return num * fn(num - 1);
    };
    console.log(jicheng(5));

    判断传入实参的个数是否与形参相等

    arguments.length实参个数

    add.length形参个数

    function add(num1, num2) {
        if (arguments.length != add.length) throw new Error('请传入' + add.length + '个参数!');
        return num1 + num2;
    }
    console.log(add(1, 1));
    console.log(add(1));
    console.log(add(1, 2, 3));

    案例:

    输出:1,1,1,1,2,3

    1、 count()()这样调用,每次都会创建一个新的局部作用域,num的值会不断地被初始化为1

    2、 return num++表示先返回num的值,再将num加1

    3、 先将count()赋给fn,此时count()只调用了一次,接下来多次调用fn()的时候,count函数并没有多次调用,num只会在count函数调用的时候被初始化,所以多次调用fn()的时候num不会被多次初始化;由于fn相当于count函数的内层函数(var fn=count();这行代码执行后,就调用了count(),调用count后就将里面的函数赋值给了fn,所以说fn就相当于函数的内层函数了。),可以访问count中的变量num,所以多次调用fn函数,会将num的值累加;

  • 相关阅读:
    10_树基础部分
    11_多线程
    14_JUC
    Servlet代码实例
    关于JSP引用资源路径
    Struts2代码实例
    hadoop三大核心组件介绍
    presto自定义函数开发
    git使用
    hive优化总结
  • 原文地址:https://www.cnblogs.com/chenyingying0/p/12143434.html
Copyright © 2011-2022 走看看