function类型
每个函数都是Function类型的实例
由于函数是对象,因此函数名实际上也是一个指向函数对象的指针。
函数的3中定义方式
使用函数声明
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; ");//不推荐,会导致2次解析代码(第一次解析常规es代码,第二次解析传入构造函数中的字符串.从而影响性能);
由于函数名仅仅是指向函数的指针,因此函数名与包含对象指针的其他变量没有什么不同。也可以说一个函数可能会有多个名字。
function sum(num1,num2){ return num1+num2; } alert(sum(10,10));//20 var anotherSum=sum;//使用不带圆括号的函数名是访问函数指针,而并非调用函数,此时anotherSum和sum指向同一个函数。因此anotherSum()也可以被调用并返回结果 alert(anotherSum(10,10));//20 sum=null; alert(anotherSum(10,10));//20
函数声明与函数表达式区别
主要在于解析器,解析器会率先读取函数声明,并使其在执行任何代码之前可用,至于函数表达式.则必须等到解析器执行到它所在的代码行,才会真正被执行
alert(sum(10,10));//20 function sum(num1,num2){ return num1+num2; }
因为解析器通过函数声明提升的过程,将函数声明添加到执行环境中,
alert(sum(10,10));//unexpected identifier 意外标识符错误 var sum=function(num1,num2){ return num1+num2; };
因为函数位于一个初始化语句中,而不是一个函数声明.也就是说在执行到函数所在的语句之前,变量sum中不会保存有对函数的引用;而且由于第一行代码就会导致意外标识符错误,也就执行终止了
除了什么时候通过变量访问函数这一点区别之外,2者的语法其实是等价的。
如果同时使用函数声明和函数表达式
var sum=function sum(){};//会在Safari中报错
函数的参数的理解
es不介意传递进来多少个参数,也不在乎参数是什么数据类型。
即便你定义的函数只接收2个参数,在调用这个函数时也未必一定要传递2个参数,可以传递一个,或者3个甚至不传递参数,而解析器不会有什么怨言。因为es中的参数在内部是用一个数组来表示的吗,函数接收到的始终是这个数组,而不关心有哪些参数。
可以通过arguments对象来访问这个参数数组,从而获取每一个参数.
函数内部属性
在函数内部有2个特殊的对象,arguments和this对象,
arguments是一个类数组对象,主要用来保存函数参数
它有一个callee属性,该属性是一个指针,指向拥有这个arguments对象的函数。
function factorial(num){ if(num<=1){ return 1; }else{ return num*factorial(num-1); } } console.log(factorial(5));//120 //用到了递归算法.这个函数的执行与函数名factorial紧紧耦合在了一起。为了消除耦合,可以用arguments.callee function factorial(num){ if(num<=1){ return 1; }else{ return num*arguments.callee(num-1); } } console.log(factorial(5));//120
this对象
this引用的是函数执行的环境对象--或者可以说是this值(当在网页的全局作用域中调用函数时,this对象引用的就是window)
window.color="red"; var o={color:"blue"}; function sayColor(){ alert(this.color); } sayColor();//"red"; o.sayColor=sayColor; o.sayColor();//blue;
//当在全局作用域中调用sayColor()时,this引用的是全局对象window,也就是说对this.color的求值会转换成对window.color求值,于是结果就返回了"red",当把这个函数赋给对象o并调用o.sayColor()时,this引用的是对象o,因此对this.color求值会转换成对o.color求值,于是返回了"blue";
caller
:这个函数对象的属性中保存着调用当前函数的函数的引用,如果在全局作用域中调用当前函数,它的值为Null
function outer(){ inner(); } function inner(){ alert(inner.caller); } outer();//会显示outer的源代码.因为outer调用了inner,所以inner.caller就指向了outer(),为了实现更松散的耦合,也可以通过 arguments.callee.caller来访问相同的信息 function outer(){ inner(); } function inner(){ alert(arguments.callee.caller); } outer();
当函数在严格模式下运行时,访问arguments.callee会导致错误