函数声明与函数表达式

函数声明通常是用函数声明语法定义的,如下例子所示。

function sum () {
        //...
}

函数表达式的定义函数的例子,如下所示。

var sum = function () {
        //...
};

以上代码定义了一个变量sum并将其初始化为一个函数。
还可以使用Function构造函数定义函数,不推荐使用

//接收任意数量参数,但最后一个参数被看做函数体,前面的参数为新函数的参数
var sum =  new Function(arg1, arg2 );

函数声明会提升到顶部。函数表达式不提升,但函数表达式定义的变量会提升,初始化时变量sum不会保存对函数的引用。

    //output: 2
    sum(1, 1);

    function sum (num1, num2) { console.log(num1 + num2); } //console.log(sum);//undefined
    //sum(1, 1);//TypeError
    // var sum = function (num1, num2) {
    // console.log(num1 + num2);
    // }

函数内部属性

在函数内部有两个特殊的对象argumentsthis
callee,是arguments的一个属性,是一个指针,指向拥有指向arguments对象的函数。

    //递归函数
    function factorial (num) {
        if (num <= 1) {
            return 1;
        } else {
            //callee指向函数factorial()
            return num * arguments.callee(num - 1);
        }
    }

this,this引用的是函数执行的环境对象。


caller函数的caller属性,该属性保存着调用当前函数的函的引用,如果在全局作用域中调用,它的值为null。

 "use strict";    

    function outer() {
        inner();
    }


    function inner() {
        // inner.caller = "a";//严格模式下不能给caller属性赋值
        console.log(inner.caller);
        //arguments.callee.caller也指向拥有指向arguments对象的函数
        // console.log(arguments.callee.caller);//严格模式下访问导致错误

    }

    outer();

    /* 输出outer()函数的源代码 ƒ outer () { inner(); } */

函数的属性和方法、

每个函数都包含两个属性lengthprototype


length表示函数希望接受的命名参数个数。

function sum (arg1, arg2, arg3) {
        //...
}

//3
console.log(sum.length);

prototype,不可枚举
引用类型的所有实例方法保存在prototype属性,通过实例访问。


每个函数包含两个非继承来的方法apply()call()
这两个方法都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。
apply()接受两个参数,一个是在其中运行的函数的作用域( 非严格模式的全局作用域下,传入this值,就是window对象。严格模式的全局作用域下,this不会转型为window, 除非明确将某个对象调用apply(),call(),否则this是undefined), 另一个是参数数组(可以是Array实例,也可以是arguments对象)。

    var color =  'red';

    function sayColor () {
        console.log(this.color);
    }

    var blue = {
        color: 'blue'
    };

    //red
    sayColor();

    //blue
    sayColor.apply(blue);

call()与apply()作用相同,区别仅在于接收参数的方式不同。call()必须明确地传入每一个参数。


使用apply(),call()来扩充作用域,好处,不用给对象额外添加方法。