1.函数的定义方式:
(1)函数声明:
(2)函数表达式:
2.能创建函数并赋值给变量也就能够将函数作为其他函数的返回值返回
3.递归
例如 :
匿名函数是指被创建的函数赋值给变量,function后面没有标识符作为函数名字
如: var functionname = function(arg0){
//函数体
}
闭包是指有权访问另一个函数作用域中的变量的函数。
创建闭包常见的方式,就是在一个函数内部创建另一个函数
如:
这是因为内部函数的作用域链包含外部函数的作用域。
作用域链详情见 :变量作用域内存
2.当某个函数被调用时,会创建一个执行环境,例如全局执行环境一般认为是为window。
例如:
定义了函数compare,又在全局作用域中调用了它。当调用函数compare()时,会创建一个包含arguments、value1、value2的活动对象。
后台的每个执行环境都有一个表示变量的对象——变量对象。
全局执行环境的变量对象始终存在(包含result和compare)它在compare作用域链中处于第二位,第一位是compare的活动对象
局部环境的变量对象只在函数执行的过程中存在
函数compare的作用域链创建过程:
1.在创建这个函数时会创建一个预先包含全局变量对象的作用域链,这个作用域被保存在内部的scope属性中
2.当调用这个函数时,会为函数创建一个执行环境,然后通过复制scope属性中的对象构建起执行环境的作用域链。
3.此后,又有一个活动对象(在此作为变量对象使用)被创建并被推入执行环境作用域的前端
对于上述函数而言,compare作用域包含两个变量对象:本地活动对象和全局变量对象。
显然,作用域链本质上是一个指向变量对象的指针列表,它只引用不实际包含变量对象。
(1)函数声明:
function functionName(arg0){
//函数体
}
alert(functionName.name);//只在firefox,safari,chrome和opera有效
函数声明提升:在执行代码前会先读取函数声明,即函数声明可以放在函数调用的语句后面
(2)函数表达式:
var functionName = function(arg0){
//函数体
}
这种形式看起来好像常规的变量赋值语句,即创建一个函数并将它赋值给变量functionName。这种情况下创建的函数也叫匿名函数(拉姆达函数),匿名函数的name属性为空字符串
2.能创建函数并赋值给变量也就能够将函数作为其他函数的返回值返回
function create(propertype){
return function(obj1,obj2){
...
};
}
此时返回了一个匿名函数,返回的函数很有可能被赋值给一个变量,或者以其他形式被调用。
3.递归
例如 :
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*factorial.callee(num-1);
}
}
可以确保无论如何调用函数都不会出现问题,但是在严格模式下不能通过脚本使用arguments.callee,不过可以使用命名函数来表达式来达成相同的结果
var factorial = (function f(num){
if(num<=1){
return 1;
}else{
return num*f(num-1);
}
});
1.匿名函数与闭包的区分
匿名函数是指被创建的函数赋值给变量,function后面没有标识符作为函数名字
如: var functionname = function(arg0){
//函数体
}
闭包是指有权访问另一个函数作用域中的变量的函数。
创建闭包常见的方式,就是在一个函数内部创建另一个函数
如:
function create(propertypeName){
return function(obj1 obj2){
var vaule1 = obj1 [propertypeName] ;
var value2 = obj2 [propertypeName];
if(value1 <value2){
return -1;
} else {
return 0;
}
}
}
内部函数访问了外部函数的变量propertypeName。即使这个函数被返回了,并且在其他地方被调用了,但是仍然可以访问变量propertypeName。
这是因为内部函数的作用域链包含外部函数的作用域。
作用域链详情见 :变量作用域内存
2.当某个函数被调用时,会创建一个执行环境,例如全局执行环境一般认为是为window。
例如:
function compare(value1 value2){
if(value1<value2){
return -1;
}
else if(value1>value2){
return 1;
}
else{
return 0;
}
}
var result = compare(5,10);
定义了函数compare,又在全局作用域中调用了它。当调用函数compare()时,会创建一个包含arguments、value1、value2的活动对象。
后台的每个执行环境都有一个表示变量的对象——变量对象。
全局执行环境的变量对象始终存在(包含result和compare)它在compare作用域链中处于第二位,第一位是compare的活动对象
局部环境的变量对象只在函数执行的过程中存在
函数compare的作用域链创建过程:
1.在创建这个函数时会创建一个预先包含全局变量对象的作用域链,这个作用域被保存在内部的scope属性中
2.当调用这个函数时,会为函数创建一个执行环境,然后通过复制scope属性中的对象构建起执行环境的作用域链。
3.此后,又有一个活动对象(在此作为变量对象使用)被创建并被推入执行环境作用域的前端
对于上述函数而言,compare作用域包含两个变量对象:本地活动对象和全局变量对象。
显然,作用域链本质上是一个指向变量对象的指针列表,它只引用不实际包含变量对象。
当函数执行完毕,局部活动对象会被销毁,但是闭包的情况又完全不同
篇幅太长不利于身心健康。。。
敬请期待:函数与闭包(下)