介绍
函数对于任何语言都是一个核心的概念,可以封装任意多条语句。
ECMAScript函数不介意传递多少函数,什么类型,因为在函数内部都是用一个数组来表示,你可以通过访问函数内部arguments对象来访问。
函数重载
传统意义上的重载,比如说在java中,可以为一个函数编写两个定义,只要接受的参数类型和数量(签名)不一样即可,但是ECMAScript参数实际上是一个数组来表
示的,所以没有签名概念,继而也不会有纯正的重载。
但是可以通过判断arugumens.length来实现重载。
function test(){
if(arguments.length == 1){...}else{...}
}
JS中的函数可以定义成
var test = function(){}
如果定义两个test函数,之后定义的函数会覆盖之前的定义,并不会实现重载。
arguments的内部属性
函数有个length属性,是函数定义时的参数的个数;相对于function.length,函数内部的arguments.length更加的动态,是函数执行时传进去的参数,有可能和
function.length不同。
arguments.callee
arguments对象有个属性(也是个对象)callee ,指向拥有这个arguments对象的函数。
阶乘函数
1 function factorial(){ 2 if(num <= 1){ 3 return 1; 4 }else{ 5 return num*(factorial(num-1)); 6 } 7 }
其中函数的执行与函数名紧密耦合了,也就是说改动函数名的话,代码也需要改动,为了消除这种耦合,可以稍作改动
function factorial(num){ if(num <= 1){ return 1; }else{ return num*(argumens.callee(num-1)); } }
* 对这个编辑器还不了解,不知道怎么修改写上去的代码,上面的括号应该改一下,还有argumens改为arguments;
arguments.callee.caller
可以用来追踪调用arguments.callee函数的函数。
函数柯里化
函数柯里化是把接受多个参数的函数变成接受单一参数的函数,我的理解就是动态成单一参数的函数,柯里化的过程就是生产新函数的过程。
比如说我要局部刷新页面,我在哪里(参数1)放入数据(参数2),这个时候需要两个参数。
但是可以通过柯里化实现调用单一参数的函数。
function update(item,W){ return function(text){ $("div#"+item).html(text + ' ' + W); } } $.ajax({ ... success:function(data){ update('divID','XOX')(data);//update('divID','XOX')就是一个柯里化的过程 } });
http://www.html5china.com/js/jsadv/20111120_2735.html
求值策略(按共享传递)
按值传递
按值传递,很多开发人员都很了解了,参数的值是调用者传递的对象值的拷贝(copy of value),函数内部改变参数的值不会影响到外面的对象(该参数在外面的值),一般来说,是重新分配了新内存(我们不关注分配内存是怎么实现的——也是 是栈也许是动态内存分配),该新内存块的值是外部对象的拷贝,并且它的值是用到函数内部的。
按引用传递
另外一个众所周知的按引用传递接收的不是值拷贝,而是对象的隐式引用,如该对象在外部的直接引用地址。函数内部对参数的任何改变都是影响该对象在函数外部的值,因为两者引用的是同一个对象,也就是说:这时候参数就相当于外部对象的一个别名。
按共享传递
函数内部给参数重新赋新值不会影响到外部的对象,但是因为该参数是一个地址拷贝,所以在外面访问和里面访问的都是同一个对象,改变该参数对象的属性值将会影响到外部的对象。
一般理论确实有按值传递的说法:但这时候这个值就是我们所说的地址拷贝(副本),因此并没有破坏规则。
简单的说,参数如果是普通类型,那么是按值传递;
如果是传递的是引用类型,对该参数(地址,指向函数外的对象)做局部修改,会影响到函数外的对象,如果对该参数(局部变量,而且是个地址)重新赋值,智慧让该参数指向一个新的对象,函数执行完之后就会销毁。
http://www.cnblogs.com/TomXu/archive/2012/02/08/2341439.html