return 语句
函数可以有return语句,也可以没有return语句。return语句能够使函数停止运行,并且把表达式的值(如果存在这样的表达式)返回给函数调用者。如果return语句没有一个相关的表达式,它会返回undefined值。如果函数不包含return语句,它就执行函数体中的每条语句,然后返回给调用者undefined。
可变长度的参数列表:Arguments对象
在函数体内,标识符arguments具有特殊含义。它是引用arguments对象的一个特殊属性。Arguments对象是一个类似数组的对象,可以按照数目获取传递给函数参数值。
Arguments允许完全的存取那些实际参数值,即使某些货全部参数还没有被命名。
和真正的数组一样,arguments具有length属性。
验证调用函数时是否使用了正确数目的实际参数。
function f(x,y,z){
if(arguments.length != 3){
alert("需要三个参数");
}
//code.....
}
函数可以接受任意多的实际参数
function max(){
var m=0;
for(var i = 0;i<arguments.length;i++){
if(arguments[i] > m) m = arguments[i];
}
return m;
}
max(1,10,2,3,4,5,6);
记住!!!!!!!arguments并非真正的数组,它是Arguments的一个对象。虽然每个Arguments对象都定义了带编码的数组元素和length属性,但是它不是数组。将它看作偶然具有了一些带编码的属性的对象更合适一些。
当函数具有了命名的参数时,Arguments对象的数组元素是存放函数参数的局部变量的同义词。arguments[]数组和命名了的参数不过是引用了同一变量的两种不同的方法。相反,用参数名改变一个参数的值同时会改变arguments[]数组获得的值。通过arguments[]数组改变参数的值同样会改变用参数名获取的值。
function f(x){
alert(x);
arguments[0] = null;
alert(x);
}
f(1); //先alert出 1 后alert出 null
如果Arguments对象是一个普通的数组,这肯定是不能所见到的行为。在这个例子中,arguments[0] 和 x 最初都引用相同的值。
属性callee
除了数组元素,Arguments对象还定义了callee属性,用来引用当前正在执行的函数。这个属性没什么太大用处,但它可以用来允许对未命名的函数递归地调用自身。
function (x){
if(x<=1)
return 1;
else
return arguments[0].callee(x-1);
}
作为数据的函数
function square(x){
return x*x;
}
这个定义创建了一个新的函数对象,并且把这个对象赋予了变量square。实际上,函数名并没有实质意义,它不过是用来引用函数变量的名字。可以将这个函数给其他的变量,它仍然会以相同的方式起作用。
var a = square(4);
var b = square;
var c = b();
除了赋给全局边变量外,还可以将函数赋给对象的属性。在这种情况下,我们称之为方法。
var o = new Object;
o.square = function(x){
return x*x;
}
y = o.square(16)
function add(x,y){return x+y};
function subtract(x,y){return x-y};
function multiply(x,y){return x*y};
function divide(x,y){return x/y};
function operate(operator,num1,num2){
return operator(num1,num2);
}
var i = operate(add,operate(add,2,3),operate(multiply,4,5));
//计算(2+3)+(4*5)
在上面的例子代码中,以operate(add,2,3)为例,第一个参数是add,持有function add 的引用,传递给operator,所以operator(2,3),相当于add(2,3)。正如上面说到的,可以把函数的引用以函数名的形式赋值给别的变量,该变量也持有了那个函数的引用。
var operators = {
add :function (x,y){return x+y},
subtract:function (x,y){return x-y},
multiply:function (x,y){return x*y},
divide:function (x,y){return x/y},
pow:Math.pow
}
function operate(op_name,num1,num2){
return operators[op_name](num1,num2);
}
var i = operate("add","Hello",operate("add"," ","World"));
alert(i);// Hello World
作为方法的函数
方法有一个非常重要的属性:在方法中,用来调用方法的对象成为关键字this的值。
var calculator = {
op1:1,
op2:1,
compute : function(){
return this.result = this.op1+this.op2;
}
}
calculator.compute();
这个this关键字很重要。任何用作方法的函数都被有效地传递了一个隐式的参数,即调用函数的对象。
当一个函数作为函数而不是方法调用的时候,这个this关键字引用全局对象。
函数的属性和方法
length
arguments数组的length属性指定了传递给函数的实际参数数目。但是函数本身的length属性的含义却并非如此,它只是只读性,返回的是函数需要的实际参数的数目,也就是在函数的形式参数列表中声明的形式参数。
function check(args){
var actual = args.length;
//获得当前运行函数的应该有的参数数目
var expected = args.callee.length;
if(actual != expected){
throw new Error("error");
}
}
function f(x,y,z){
check(arguments);
return x+y+z;
}
f(1,2) //会输出error信息
方法apply()和call()
ECMAScript规范给所有函数定义了两个方法call()和apply().使用这两个方法可以像调用其他对象的方法一样调用函数。call()和apply()的第一个参数都是要调用的函数的对象,在函数体内这一参数是关键字this的值。例如,要把两个数字传递给函数f(),并将它作为对象o的方法调用,可以使用如下代码:
f.call(o,1,2);
这与下面的代码相似:
o.m = f;
o.m(1,2);
apply()和call()很相似,只不过要传递给函数的参数是由数组指定的:
f.apply(o,[1,2]);