1、JavaScript中定义函数有2钟方法:
1-1.函数声明:
复制代码 代码如下:
function funcName(arg1,arg2,arg3){
//函数体
}
①name属性:可读取函数名。非标准,浏览器支持:FF、Chrome、safari、Opera。
②函数声明提升:指执行代码之前会先读取函数声明。即函数调用可置于函数声明之前。
1-2.函数表达式:
复制代码 代码如下:
var funcName = function(arg1,arg2,arg3){
//函数体
};
①匿名函数(anonymous function,或拉姆达函数):function关键字后无标识符,name属性值为空字符串。在把函数当成值使用时,都可用匿名函数。
②类似其他表达式,函数表达式使用前需先赋值,故不存在"函数声明提升"那样的作用。
③ECMAScript中的无效函数语法:
复制代码 代码如下:
if判断中的重复函数声明
if(condition){
function sayHi(){
alert("Hi!");
}
} else {
function sayHi(){
alert("Yo!");
}
}
浏览器JavaScript引擎修正错误差异:大多浏览器会返回第二个声明,忽略condition;FF则会在condition为true时返回第一个声明。
使用函数表达式可解决并实现:
复制代码 代码如下:
if判断 函数表达式
var sayHi;
if(condition){
sayHi = function(){
alert("Hi!");
}
} else {
sayHi = function(){
alert("Yo!");
}
}
2、递归
递归函数,是在一个函数中通过名字调用自身的情况下构成的。
复制代码 代码如下:
function factorial(num){ //一个经典的递归阶乘函数
if (num <= 1){
return 1;
} else {
return num * factorial(num-1);
}
}
①若使用下列代码调用该函数,会出错:
复制代码 代码如下:
var anotherFactorial = factorial;
factorial = null;
alert(anotherFactorial(4));
将factorial()函数保存到变量anotherFactorial中后,将factorial变量设为null后不再引用函数,而anotherFactorial(4)中要执行factorial()函数,故出错。
使用argument.callee(指向正在执行的函数的指针)可解决:
复制代码 代码如下:
解决方案
function factorial(num){
if (num <= 1){
return 1;
} else {
return num * arguments.callee(num-1);
}
}
var anotherFactorial = factorial;
factorial = null;
alert(anotherFactorial(4)); //24
在非严格模式,使用递归函数时,用argument.callee代替函数名更保险
在严格模式下,使用argument.callee会出错,可用函数表达式 代替 函数声明:
复制代码 代码如下:
函数表达式代替函数声明
var factorial = function f(num){
if (num <= 1){
return 1;
} else {
return num * f(num-1);
}
}
4、闭包
指有权访问另一个函数作用域中的变量的函数。(常见形式为函数嵌套)
复制代码 代码如下:
function wai(pro){
return function(obj1,obj2){
var val1 = obj1[pro];
var val2 = obj2[pro];
if(val1<val2){
return -1;
}else if(val1>val2){
return 1;
}else{
return 0;
};
}
}
return匿名函数时,匿名函数的作用域链初始化为包含函数的活动对象和全局变量对象。即匿名函数包含wai()函数的作用域。
每个函数被调用时,会创建一个执行环境、一个变量对象 及 相应的作用域链。
4-1.执行环境 及 作用域