毫无疑问,john resig 是一个细致且善于思考的人,对于我们通常使用的匿名函数,在他的细究之下,也能挖掘出一些新的东西。通常情况下,当一个函数调用自身时,递归就出现了,对于下面这样的函数调用,我们并不陌生。
1.function yell(n){
2. return n > 0 ? yell(n-1) + "a" : "hiy";
3.}
4.alert( yell(4))//结果为:hiyaaaa;
单个函数看不出任何问题,如果我们使用匿名函数,并将其放置到一个对象内部,结果会怎样?
1.var ninja = {
2. yell: function(n){
3. return n > 0 ? ninja.yell(n-1) + "a" : "hiy";
4. }
5.};
6.alert( yell(4))//结果为:hiyaaaa;
现在我们看不出任何问题所在,如果我们创建一个新的对象,从ninja 那里复制yell方法,情况就有所不同了。既然匿名函数在ninja 内部,那么该方法仍是对ninja对象yell方法的引用。如果我们重新定义ninja对象,问题就出现了。
01.var ninja = {
02. yell: function(n){
03. return n > 0 ? ninja.yell(n-1) + "a" : "hiy";
04. }
05.};
06.var samurai = { yell: ninja.yell };
07.var ninja = {};
08.try {
09. alert(samurai.yell(4);
10.} catch(e){
11. alert("uh, this isn't good! where'd ninja.yell go?" );
12.}
13.//结果是:"uh, this isn't good! where'd ninja.yell go?"
如何解决该问题?如何使yell方法更可靠?最常见的方法是在ninja.yell方法内部使用“this”来改变ninja对象的所有实例,即:
1.var ninja = {
2. yell: function(n){
3. return n > 0 ? this.yell(n-1) + "a" : "hiy";
4. }
5.};
现在我们测试,将会得到我们需要的结果。这当然是一种方法,另外一种方法是给匿名函数命名,这看似矛盾,但的确能很好的工作,瞧:
01.var ninja = {
02. yell: function yell(n){
03. return n > 0 ? yell(n-1) + "a" : "hiy";
04. }
05.};
06.alert((ninja.yell(4)) + " works as we would expect it to!" );
07.var samurai = { yell: ninja.yell };
08.var ninja = {};
09.alert( (samurai.yell(4))+ " the method correctly calls itself." );
给匿名函数命名可以更进一层,对于正常的变量声明,我们也可以尝试这样做,如:
1.var ninja = function myninja(){
2. alert( (ninja == myninja) + " this function is named two things - at once!" );
3.};
4.ninja();
运行上面的这个函数,在 ie中,我么看到的是:”flase this function is named two things – at once!”,在ff中我们看到的是:”true this function is named two things – at once!”。作者曾指出:匿名函数可以命名,但只在函数自身内部可见。看来并不是那么回事,测试结果表明,对于ie,并不可见,而在ff中,结果正如作者所料。同时,我们检测myninja,结果在ie和ff也有所不同。
1.alert( typeof myninja);
2.//在ff中为"undefinde"
3.//在ie中为"function"
这样看来,给匿名函数命名,在ie中,只在外部可见;在ff中,只在函数内部可见。其实,我们可以使用arguments.callee获得我们所需要的结果,如下:
1.var ninja = {
2. yell: function(n){
3. return n > 0 ? arguments.callee(n-1) + "a" : "hiy";
4. }
5.};
6.alert( ninja.yell(4));
arguments.callee是对于每一个函数都可以使用,它提供给我们一个可靠的方法去访问函数自身。本人觉得,该方法比较简洁可靠。
综上所述,所有这些方法对我们处理复杂的代码结构将大有裨益。选择使用可以使我们的代码结构更加简洁明了,这也许是作者的初衷。
新闻热点
疑难解答