js函数特性

作者: 慕凌峰 | 来源:发表于2018-07-16 22:25 被阅读1次

    | 上一章 |目录| 下一章 |

    三、js函数特性

    1、参数可边长函数

    function main(arg1,arg2) {
        alert(arg1);
    }
    
    // 可以传递任意多个参数
    main(1);
    
    main(1,2);
    
    main(1,2,3);
    ...
    
    • 也可以不给函数定义形参,直接用arguments属性来接受实际传入的参数数组。
    function main(){
        var args = arguments;
        // 4
        alert(args.length);
        // 1
        alert(args[0]);
    }
    
    main(1,2,3,7);
    

    2、函数不能重载

    • 后面的函数会覆盖掉前面的函数

    js中不会像java中,根据传入的参数来判断选择哪个函数,因为在js中,所有的方法都是可变长度的

    此外,javascript是一种解释执行的语言,在浏览器的脚本引擎开始载入你的js代码时,必然会进行“扫描”,然后再开始解释执行,在这个过程中,“标识符解析”是一个必不可少的重要操作,它要求同一命名空间中不允许有同名的变量存在,函数也是。

    function myFunc(){
        alert("func1");
    }
    
    function myFunc(arg){
        alert("func2");
    }
    
    function myFunc(){
        alert("func3");
    }
    
    // func3
    myFunc();
    
    // func3
    myFunc(3);
    

    3、函数嵌套

    3.1 内部函数

    当外部函数 outerFunc调用结束之后,innerFunc函数也会从内存中消失,不会留下任何的痕迹。而且,对于outerFunc函数外部的代码来说,innerFunc函数是不存在的,不可见。

    function outerFunc(){
        function innerFunc(){
            alert("innerFunc");
        }
        innerFunc();
        alert("outerFunc");
    }
    
    outerFunc();
    
    • 如何让外部代码调用内部函数

    词法作用域:对于innerFunc来说,outerFunc函数大括号里面的“封闭区域”就叫做innerFunc的词法作用域。

    function outerFunc() {
        function innerFunc() {
            alert("innerFunc");
        }
        
        // 返回一个函数指针
        return innerFunc;
    }
    
    var cache = outerFunc();
    cache();
    
    • 当执行 cache() 的时候,按道理,变量 name 应该随着var cache = outerFunc();中outerFunc函数的执行完毕而不存在,但是依然能够获取到name的属性值,说明

      • innerFunc 在实际执行的时候,一定还在它的词法作用域中,即outerFunc函数的内部,否则它不可能访问到name
      • 说明name还没有被内存回收,或者name被存储在某个地方(后续具体介绍)。
    var outerName = "outerName";
    
    function outerFunc() {
    
        var name = "name";
        
        function innerFunc() {
            alert("outerName = " + outerName + ", " + "name = " + name);
        }
        
        // 返回一个函数指针
        return innerFunc;
    }
    
    var cache = outerFunc();
    // "outerName = outerName, name = name
    cache();
    

    4、call/apply/自执行

    会看到两次输出的 this.name的值是不一样的,这就是javascript的动态性(javascript是一门动态语言

    java中的this总是指向当前对象,而javascript中的this并不一定指向特定的对象,它是可变的

    function myFunc() {
        alert(this.name);
    }
    
    // 小明
    myFunc.call({name:"小明"});
    
    
    // 小三
    myFunc.apply({name:"小三"});
    
    • call()、apply()的比较
      • call 和 apply 都可以接收两个参数,第一个参数为函数中this需要绑定的对象,因此对于第一个参数的处理,call与apply是一致的。

      • 但对于第二个参数就不同了,call的第二个参数使用的是可变长度参数,但apply 的第二个参数是一个数组。

    myfunc.call({},var1,var2,var3...);
    myFunc.apply({},[var1,var2,var3]);
    

    5、函数也是数据,也是对象

    5.1 函数是数据

    • 1
    function myFunc() {
        alert("this is my funcion");
    }
    // 输出
    // 
    // function myFunc() {
    //    alert("this is my funcion");
    // }
    alert(myFunc);
    
    • 2
    var myFunc = function() {
        alert("this is my funcion");
    }
    // 输出
    // 
    // function myFunc() {
    //    alert("this is my funcion");
    // }
    alert(myFunc);
    
    • 1 和 2 的比较

      • 效果完全相同

      • 构造时机不同:1 和 2 两个例子的运行结果虽然是相同的,但是他们的运行细节确实不相同的,1 中直接声明了一个函数,这个函数会在脚本引擎解析期间创建,而 2 中的方式其实是定义了一个变量,而不是函数,所以,只有在脚本真正被执行的时候,函数才会真正的被创建出来。

    5.2 函数是对象

    • 1 利用内置构造器 Function 创建一个函数
    var fn = new Function('x', 'y', 'alert("Just coding!")');
    
    // true
    alert(fn instanceof Object);
    
    // Just coding!
    fn();
    
    • 2
    var fn = = function() {
        alert("Just coding!");
    }
    
    // true
    alert(fn instanceof Object);
    
    // Just coding!
    fn();
    

    Function 的构造器可以接受任意多个参数,最后一个参数会被当作“函数体”,之前的所有参数都会被当作“函数的参数”。

    • 1 和 2 的比较

      • 效果完全相同

      • 构造时机不同:1 和 2 两个例子的运行结果虽然是相同的,但是他们的运行细节确实不相同的,1 中直接声明了一个函数,这个函数会在脚本引擎解析期间创建,而 2 中的方式其实是定义了一个变量,而不是函数,所以,只有在脚本真正被执行的时候,函数才会真正的被创建出来。

      • 作用域不同:new Function() 创造出来的函数,其作用域指向“顶级作用域”,即 Window

    6、函数实例的属性

    6.1 length

    获取函数定义的形参个数

    • 注意: javascript 函数的参数个数是可变的,但是,那指的是函数在操作时的实际参数(实参),而这里指的是 形参
    function myFunc(arg1,arg2){
        
    }
    // 2
    alert(myFunc.length);
    

    6.2 arguments

    尅获取到所有的 实参,类似于数组,以为它只有一个length属性,而没有数组拥有的其他属性

    但可以将它转化为一个真正的数组

    function myFunc(){
        var s = "";
        var len = arguments.length;
        for(var i=0; i < len; i++) {
            s+= arguments[i];
        }
        alert(s);
    }
    
    // 1234
    myFunc(1,2,3,4);
    
    • arguments转换为数组
    var args = Array.prototype.slice.call(arguments);
    

    6.3 callee

    callee是在arguments属性中定义的。

    (
        function test() {
            alert(arguments.callee);
        }
    )();
    
    // 结果:
    // function test() {
    //         alert(arguments.callee);
    // }
    
    • **通过 callee 可以实现递归
    ...
    fact(n) {
        if() {
            return 1;
        } else {
            return n * arguments.callee(n-1);
        }
    }
    ...
    

    6.4 caller

    它指向调用者,因此可以通过这个属性知道谁在调用自己

    • 注意: 因为caller指向调用者,所以,它在函数运行时,才会被定义,如果在顶级作用域Window直接调用 code() 函数,那么caller值为undefined,在IE中为null;
    function code() {
        alert(code.caller);
    }
    
    function beatHim() {
        code();
    }
    
    beatHim();
    
    // 结果:
    // function beatHim() {
    //     code();
    // }
    
    

    |上一章 |目录| 下一章|

    相关文章

      网友评论

        本文标题:js函数特性

        本文链接:https://www.haomeiwen.com/subject/zosipftx.html