函数的基本语法如下所示:
function functionName(arg0, arg1,...,argN) {
statements
} 函数如果有返回值则return 后的语句将不会被执行,返回值可以直接在return语句中实现,没有return返回的undefined
函数中的参数:
1.函数中不介意传递的参数个数和参数的类型,函数中的参数其实是一个数组,可以通过arguments 来访问参数
2.函数中的参数不能重载,ECMAScript 中定义了两个名字相同的函数,则该名字只属于后定义的函数
Function类型
函数实际上是Function类型的实例,函数名相当于只想函数对象的指针,它与其他引用类型一样有属性和方法。
由于函数名仅仅是指向函数的指针,因此函数名与包含对象指针的其他变量没有什么不同。函数作为另一个函数的参数或者另一个函数的返回值(函数的嵌套)换句话
说,一个函数可能会有多个名字,如下面的例子所示。
function sum(num1, num2){
return num1 + num2;
}
alert(sum(10,10)); //20
var anotherSum = sum;
alert(anotherSum(10,10)); //20
sum = null;
alert(anotherSum(10,10)); //20
FunctionTypeExample01.htm
以上代码首先定义了一个名为sum()的函数,用于求两个值的和。然后,又声明了变量anotherSum,
并将其设置为与sum 相等(将sum 的值赋给anotherSum)。注意,使用不带圆括号的函数名是访问函
数指针,而非调用函数。此时,anotherSum 和sum 就都指向了同一个函数,因此anotherSum()也
可以被调用并返回结果。即使将sum 设置为null,让它与函数“断绝关系”,但仍然可以正常调用
anotherSum()。ECMAScript 中的函数名本身就是变量,所以函数也可以作为值来使用。也就是说,不仅可以像传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回。
函数声明三种方法:
function sum (num1, num2) {
return num1 + num2;
}
函数表达式声明
var sum = function(num1, num2){
return num1 + num2;
};
一种定义函数的方式是使用 Function 构造函数。Function 构造函数可以接收任意数量的参数,
但最后一个参数始终都被看成是函数体,而前面的参数则枚举出了新函数的参数。来看下面的例子:
var sum = new Function("num1", "num2", "return num1 + num2"); // 不推荐
函数表达式和函数声明的比较
函数声明提升:在函数执行前,解析器会先读取函数的声明 ,再调用相应函数
函数内部的对象:this(函数执行环境的对象),arguments(类数组对象,保存函数的参数)
函数内部的属性length:函数中接受参数的个数,prototype
函数内部的方法:apply ()和call()
。这两个方法的用途都是在特定的作
用域中调用函数,实际上等于设置函数体内this 对象的值。首先,apply()方法接收两个参数:一个
是在其中运行函数的作用域,另一个是参数数组。其中,第二个参数可以是Array 的实例,也可以是
arguments 对象。例如:
function sum(num1, num2){
return num1 + num2;
}
function callSum1(num1, num2){
return sum.apply(this, arguments); // 传入arguments 对象
}
function callSum2(num1, num2){
return sum.apply(this, [num1, num2]); // 传入数组
}
alert(callSum1(10,10)); //20
alert(callSum2(10,10)); //20
在严格模式下,未指定环境对象而调用函数,则this 值不会转型为window。
除非明确把函数添加到某个对象或者调用apply()或call(),否则this 值将是
undefined。
apply()和call()真正的用武之地;它们真正强大的地方是能够扩充函数
赖以运行的作用域
匿名函数: 创建的 函数赋值给变量
http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
http://www.cnblogs.com/rainman/archive/2009/05/04/1448899.html
(全局变量会保存在内存中,局部变量函数执行后会被销毁) 区分好全局和局部
闭包:闭包是指有权访问另一个函数作用域中的变量的函数(函数嵌套)。由于闭包会携带包含它的函数的作用域,),作用域链终点的全局执行环境 作用:可以在函数外部读取函数内部的局部变量,另一个就是让这些变量的值始终保持在内存中。(即闭包指的是函数嵌套中的内部函数所以这些变量指外部函数中包含的变量)
因此会比其他函数占用更多的内存
闭包副作用:,即闭包只能取得包含函数中任何变量的最后一个值
function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = function(){
return i;
};
}
return result;
}//都是返回10
function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = (function(num){
return function(){
return num;
};
})(i);
}
return result;
}//1,2,3…..10
递归函数(一个函数通过名字调用自身)
function factorial(num){
if (num <= 1){
return 1;
} else {
return num * factorial(num-1);
}
}
。虽然这个函数表面看来没什么问题,但下面的代码却可能导致它出错。
var anotherFactorial = factorial;
factorial = null;
alert(anotherFactorial(4)); //出错!
arguments.callee 是一个指向正在执行的函数的指针,因此可以用它来实现对函数
的递归调用
function factorial(num){
if (num <= 1){
return 1;
} else {
return num * arguments.callee(num-1);
}
在严格模式下,不能通过脚本访问arguments.callee,访问这个属性会导致错误。不过,可
以使用命名函数表达式来达成相同的结果。例如:
var factorial = (function f(num){
if (num <= 1){
return 1;
} else {
return num * f(num-1);
}
});