引用类型之function

函数的创建

  • 函数声明
  • 函数表达式
  • 使用Function()构造函数(不推荐)
//函数声明
function sum(num1,num2){
    return num1+num2;
}

//函数表达式,注意函数表达式后有个分号,像声明变量一样
var sum = function(num1,num2){
    return num1+ num2;
};

//使用Function()构造函数,可以接受任意数量的参数,最后一个参数是函数体,前面都是函数参数,不推荐,会导致解析两次函数代码
var sum= new Function('num1', 'num2' , 'return num1+num2;');

函数是对象

每个函数是对象,都是Function的实例,所有都拥有属性和方法,所以他们还是Object的实例。因此,函数名只是一个指向函数对象的指针,不会与某个函数保持绑定。并且函数名和其它变量没有什么不同,一个函数可能有多个名字,比如

function sum(num1,num2){
    return num1+num2;
}

var anothersum = sum;//注意,函数名不带()表示访问的是函数指针

anothersum(10,10);//20

sum = null; //清空引用,让它与函数断绝关系,但仍然可以访问anothersum();

没有重载

重载就是函数具有相同的函数名,但是根据不同的参数类型和个数,系统调用函数时选择不同的功能进行调用,就是一个函数多个功能。但是js中函数是对象,函数名为指针,意味着仅仅是个变量,因此不能根据函数名来选择不同的功能,但是可以通过判断arguments这个参数对象,内部实现,这样我们不用记那么多的api,jquery就是这么干的,比如

$().css('weight');//获取宽度
#().css('weight','200px');//设置宽度

函数声明提升

关于函数声明和函数表达式,解析器对他们的处理是不同的,解析器会率先读取函数声明,并在执行任何代码之前可用,而函数表达式,必须等到解析器执行到该位置时才真正被解释执行,比如

//函数声明提升,即在代码执行之前,通过函数声明提升,读取并将函数声明添加到执行环境中,js引擎会在第一遍就声明函数并放到源代码树的顶部。所以下面:
alert(sum(10,10);//这是可以的
function sum(num1,num2){
    return num1+num2;
}

alert(sum(10,10);//错误
var sum= function(num1,num2){
    return num1+num2;
}

//也可以同时使用,不过一没必要,二safari会报错

作为值的函数

函数名本身就变量,所以可以当值来使用,也就是说可以当做参数把一个参数传给一个函数,还可以将一个函数作为另一个函数的结果返回。在设计模式中,对象的多态性通过这个能够很好的替代。但是,必须记住传的时候不能带(),这个表示调用,并不是指针。
作为参数----可以实现类似对象的多态
作为函数返回-----可以实现更有意思的功能。

函数内部属性

  • arguments--类数组对象,包含传入的所有参数,通过它,模拟函数重载
  • this--引用的是函数据以执行的变量对象(作用域),注意不是该函数为变量对象,是该函数所在的变量对象,全局就是window
  • caller--保存的是调用当前函数的函数的引用
    这两个都是对象,arguments有一个callee属性,该属性是一个指针,指向拥有这个arguments的函数,阶乘函数
function factorial(num){//递归算法
    if(num<=1){
        return 1;
    }else{
        //return num*factorial(num-1);这样就和函数名耦合了
        return num*arguments.callee(num-1);//完成正常的递归调用
    }
}

关于this.这个要特别注意的了,不同的调用方式以为着不同的this值,算是js的一个大坑,后面再说

关于caller,除了早期opera,都支持,

function outer(){
    inner();
}

function inner(){
    alert(inner.caller);
}

outer();//显示outer的源代码

//实现松耦合
function inner(){
    alert(arguments.callee.caller);
}

在严格模式下,不能访问arguments.callee,es5还定义了argumens.caller,不过严格模式下出错,非严格为undefined,所以压根没什么用,仅仅是为了区分这个arguments.caller和函数的caller的区别。严格模式还不能为函数的caller属性赋值。

posted @ 2016-06-10 22:18  idoujiao  阅读(194)  评论(0)    收藏  举报