腊月的季节

函数类型回顾

匿名函数的调用

function(a){return a;}

  • 我们可以将匿名函数作为参数传递给其他函数,这样,接收方函数就能利用我们所传递的函数来完成某些事情。
  • 我们可以定义某个匿名函数来执行某些一次性任务。
    实例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function invoke_and_add(a,b){
    return a()+b();
    }
    function one(){
    return 1;
    }
    function two(){
    return 2;
    }
    invoke_and_add(one,two);

这也就是下面要说的回调函数。

回调函数

回调示例:

1
2
3
4
5
6
7
8
9
10
function multiplyByTwo(a,b,c){
var i,ar=[];
for(i=0;i<3;i++){
ar[i]=arguments[i]*2;
}
return ar;
}
function addOne(a){
return a+1;
}

测试
>>>multiplyByTwo(1,2,3);
[2,4,6]
>>>addOne(100)
101
>>>var myarr=[];
>>>myarr=multiplyByTwo(10,20,30);
[20,40,60]
>>>for(var i=0;i<3;i++){myarr[i]=addOne(myarr[i]);}
>>>myarr
[21,40,60]
回调改善

1
2
3
4
5
6
7
function multiplyByTwo(a,b,c,callback){
var i,ar=[];
for(i=0;i<3;i++){
ar[i]=callback(arguments[i]*2);
}
return ar;
}

自调函数

1
2
3
4
5
{
function(){
alert('boo');
}
}();

内嵌函数

1
2
3
4
5
6
function a(param){
function b(theinput){
return theinput*2;
};
return 'The result is'+b(param);
};
1
2
3
4
5
6
var a=function(param){
var b=function(theinput){
return theinput*2;
};
return 'The result is'+b(param);
}

>>> a(2);
“The result is 4”
>>> a(8);
“The result is 16”
>>> b(2)
b is not defined

以函数为返回值的函数

实例:

1
2
3
4
5
6
function a(){
alert('A!');
return function(){
alert('B!');
};
}

>>> var newFunc=a();
>>> newFunc();

能重定义自身的函数

实例:

1
2
3
4
5
6
function a(){
alert('A!');;
a=function(){
alert('B!');
};
}

闭包

利用闭包突破作用域链
闭包1实例:

1
2
3
4
5
6
function f(){
var b="b";
return function(){
return b;
}
}

>>> b
b is not defined
接下来,我们来看一下f()的返回值。这是另一个函数,我们可以把它看做上图中的函数N,该函数有自己的使用空间,同时也可以访问f()的空间和全局空间,所以b对它来说也是可见的。因为f()是可以在全局空间中被调用的,所以我们可以将它的返回值赋值给另一个全局变量,从而生成一个可以访问f()私有空间的新全局函数。
闭包2实例:

1
2
3
4
5
6
7
var n;
function f(){
var b="b";
n=function(){
return b;
}
}

>>> f();
我们在f()中定义了一个函数,并且没有在这里使用var语句,因此它应该是属于全局的,由于n()是在f()内部定义的,它可以访问f()的作用域,所以即使该函数后来升级成了全局函数,但它依然可以保留对f()作用域的访问权。
>>> n()
“b”
闭包3实例:

1
2
3
4
5
6
7
function f(arg) {
var n=function(){
return arg;
};
arg++;
return n;
}

>>> var m=f(123);
>>> m();
124
循环中的闭包
实例:

1
2
3
4
5
6
7
8
9
10
function f(){
var a = [];
var i;
for(i = 0;i < 3;i++){
a[i] = function(){
return i;
}
}
return a;
}

>>> var a = f()
这时我们得到了一个数组函数,就来执行吧
>>> a[0]()
3
>>> a[1]()
3
>>> a[2]()
3
你们大概想的都是0,1,2吧,但是其实不然,因为这跟内存有关了,i是一个变量名,它指向的是i的内存,内存里面是什么,它就会是什么,那么最后一次循环,是从i=3结束的,所以i最终等于3.那么输出的也就是3.
显然我们需要三个三个变量或者选择闭包。

1
2
3
4
5
6
7
8
9
10
11
12
function f(){
var a = [];
var i;
for(i = 0;i<3;i++){
a[i] = (function(x){
retrun function(){
return x;
}
})(i);
}
return a;
}

这样就能获得我们预期的结果了
>>> var a = f();
>>> a[0]();
0
>>> a[1]();
1
>>> a[2]();
2
或者我们也可以定义一个正常点,不使用自调函数的内部函数来实现相同的功能。关键是在每次迭代操作中,我们要在中间函数内将i的值本地化。

1
2
3
4
5
6
7
8
9
10
11
12
13
function f(){
function makeClosure(x){
return function(){
return x;
}
}
var a = [];
var i;
for(i=0;i<3;i++){
a[i] = makeClosure[i];
}
return a;
}

热评文章