日期:2014-05-16 浏览次数:20374 次
??? 如果要问JavaScript里面什么最有趣,当属函数了。因为每个函数都是Function类型的实例。
??? JS中Function类型的构造函数,可以接受任意数量的参数,但最后一个参数始终都被看成是函数体。例如下面的定义方式在JS语法里完全合理:???
???
var sum=new Function("num1","num2","return num1+num2"); alert(sum(1,2));//输出3
?但是这种方式除了可以用来理解函数也是对象,函数名是指针之外,就一无是处了。因为这种方法将导致解析ECMAScript两次代码。第一次是常规的解析,第二次是解析函数体内容。所以这种方式并不推荐,忘掉这种方式吧
?? 下面两种方式都是可以的,第一种方式大家都很熟悉:
????
function sum(num1,num2){ return num1+num2; }
?
? 第二种方式,姑且可以理解为函数字面量定义法吧,哈哈~
??
var sum=function(num1,num2){ return num1+num2; } //这里声明了一个函数对象,并让指针sum(准确的说是引用对象)指向了这个函数对象
?
理解了“函数是对象,函数名是指针”之后,就不难理解为什么JS里函数没有重载的原因了。请看:
???
function sum(num1){ return num1+10; } function sum(num2){ return num2+50; } alert(sum(10));//输出60
?
这段代码事实上与下面这段代码并没有什么区别:
??
var sum=function(num1){ return num1+10; } sum=function(num2){ return num2+50; } alert(sum(10));
?
?? 通过这段代码大家就可以发现,sum这个引用对象重新指向了新的函数对象,所以就造成了函数没有重载的原因。事实上这个原理也同样可以用来解释为什么Python里也没有函数重载的原因。
?
?? 这里有必要阐述下函数声明与函数表达式声明之间的区别。JS解释器在解析JS代码的时候,首先会读取函数声明,并使其在执行任何代码之前可以访问;至于函数表达式,则必须等到解析器执行到它所在的代码中,才会真正的被执行。
?? 例如:
??
alert(sum(10));//没有问题,可以正确的输出20 function sum(num){ return num+10; } alert(sum(10));//解析错误,报unexpeced identifier(意外标识符错误) var sum=function(num){ return num+10; }
?
?
?? JS的具体解释法则我不是很清楚,不过按照Python的解释法则,貌似可以稍微理解下。
?? 在Python中,解释器首先会解释加载所有顶级无缩进的代码(按照先后顺序),由于在Python中没有var sum=function(){}这样的定义函数的方法,所以在Python中不会有这种函数定义前后顺序的问题。但如果调用一个之后定义的函数,还是会有这个问题。
???? 例如:
????
foo();#解释出错,提示foo变量未定义 def foo(): print 123; def foo(): boo(); def boo(): print 123; foo();#没有问题,可以直接输出123 #理由是python解释器在解释执行的时候, #按照无缩进的代码先后顺序加载,这个过程 #只确保它们可以被访问
?
?? JS函数对象中,有两个特殊的内部属性,分别为arguments和this,下面分别介绍下这两个参数:
??arguments属性用来保存当前函数的参数数组,它事实上也是个对象,它还有个名叫callee的属性,这是一个指针,用来指向拥有这个arguments对象的函数对象。例如:
???在经典的阶乘函数里,Factorial函数可能如下所示:
??
function factorial(num){ if(num==1){ return num; }else{ return num*factorial(num-1); } }
?这个函数在大多数情况下可以工作的很好,但它有一个隐性的问题,就是它的递归函数里与函数名(实质是指针)完全耦合在一起。如果以后想让这个函数名指向其他的函数,则这个方法将完全不能工作,解耦它的方式是这样的:
???
function factorial(num){ if(num==1){ return num; }else{ return num*arguments.callee(num-1); } }
?
?函数的另外一个属性就是this,它表示函数在执行的时候所处的作用域.如果函数位于全局作用域范围,那么这个时候,可以解析为window。如果函数位于某个对象的声明范围内,那么则解析为当前对象。例如:
??
var color="red"; var my={ color:"blue" } function sayHello(){ alert(this.color); } sayHello();//这时候把this解析为window,相当于访问window.color my.sayHello=sayHello; my.sayHello();//这个时候把this解析为this,相当于访问my.color
?
?