JavaScript引用类型-函数
Function类型是ECMAScript引用类型中的一种,它就是我们熟悉的函数。有意思的是,在ECMAScript中,函数实际上是对象。
每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法。
由于函数是对象,因此函数名实际上就是指向这个函数对象的指针,不会与某个函数绑定。
定义函数的三种方式:
1.使用函数声明语法。
function sum(num1,num2){ return num1+num2; }
2.使用函数表达式定义。
var sum = function(num1,num2){ return num1+num2; };通过变量名称sum即可引用这个函数,sum();
因为是使用表达式定义,所以别忘了表达式要以;结尾。
3.使用Function构造函数。Function构造函数接收任意数量的参数,并且把最后一个参数看成函数体。
但这种方式性能不好,已不推荐使用。
var sum = new Function("num1","num2","return num1+num2");
我们需要注意的是,函数名仅仅是指向这个函数对象的一个指针,也就是一个变量而已,一个函数可能会有多个名字,就像一个对象可以被多个指针引用一样。
例如上面的sum变量,当我们要调用函数时,用函数加上圆括号,sum(1,2);。而不带括号的函数名sum表示的是我们访问这个函数指针,而不是调用函数。在当把函数作为值传递时要注意这点。
理解了函数名只是一个指针,那也就可以理解为什么ECMAScript中没有函数重载了,当我们写了两个同名的函数时,只不过是把这个函数名代表的指针指向了后写的那个函数对象,执行的结果看上去就是前一个函数被后一个同名的函数替代了。
之前说到定义函数的两种方式,函数声明和函数表达式。它们在定义函数时作用是一样的,但是在解析器在向执行环境(比如浏览器)加载我们的js代码时,对这两种函数定义的加载顺序是不一样的。
解析器会先读取函数声明,并使其在执行任何代码前可以被访问;至于函数表达式,则只有等到解析器执行到它所在的那行代码时,才会被解释然后执行。例如:
alert(sum(1,2)); //可以执行 //虽然函数声明写在函数调用的后面 function sum(num1,num2){ return num1+num2; }
但下面这样就不行:
alert(sum(1,2)); //产生错误 //函数表达式 var sum = function(num1,num2){ return num1+num2; };
由于在ECMAScript中,函数名本身就是变量,所以函数也可以当做值来使用。也就是说,不仅可以像传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回。
function callFunction(function,argument){ return function(argument); } function add(num){ return num + 100; } var result = callFunction(add,100); alert(result); //200
在函数的内部,有两个特殊的对象:arguments和this。
arguments对象与数组类似,里面包含着传入函数中的所有参数,可以使用数组的方括号语法来访问。ECMAScript函数不介意传递进来多少参数,也不在乎传递进来参数的类型,你可以定义一个接收两个参数的函数,但使用时可以传递任意个参数,或者一个也不传。因为对于ECMAScript函数来说,命名的参数只不过是为我们在函数体使用参数时提供了便利,它并不是必须的,在函数体内可以使用arguments对象来得到传递给函数的每一个参数。
此外,arguments对象还有一个callee属性,该属性是一个指针,指向拥有这个arguments对象的函数。
函数的另一个特殊对象是this,这个this的行为和Java中的this类型。this引用的是函数据以执行的环境对象。(当在全局作用域中调用某个函数时,this对象引用的就是window这个全局对象)。
window.color = "red"; var o = {color : "yellow"}; function sayColor(){ alert(this.color); } sayColor(); //red o.sayColor = sayColor; o.sayColor(); //yellow在sayColor函数调用之前,this的值并不确定。在全局环境中调用sayColor(),this的值就是window。当调用o.sayColor()时,this引用的就是对象o。
函数的属性:length和prototype。
length属性比较简单,它表示函数希望接收的命名参数的个数,就是定义函数时定义的参数的个数。
prototype属性,就是函数对象得到原型属性,这个在介绍对象的时候介绍过。这里不再展开。
函数的方法:
每个函数都包含两个非继承而来的方法:apply()和call()。
这两个方法的用途都是在特定的作用域中调用函数,实际上也就是用来设置函数体内this对象值。
这两个方法的区别仅仅在于接收参数的方式不同,当不给函数传递参数的时候,使用哪个方法都无所谓。
window.color = "red"; var o = {color : "yellow"}; function sayColor(){ alert(this.color); } sayColor.apply(o); //yellow sayColor.call(o); //yellow sayColor(); //red sayColor.call(window); //red
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。