search

Home  >  Q&A  >  body text

javascript - js命名函数表达式的问题

var ninja = {
  yell: function(n){
    return n > 0 ? ninja.yell(n-1) + "a" : "hiy";
  }
};
console.log(ninja.yell(4) == "hiyaaaa");

var samurai = { yell: ninja.yell };
var ninja = null;

samurai.yell(4);


var ninja = { 
  yell: function yell(n){ 
    return n > 0 ? yell(n-1) + "a" : "hiy"; 
  } 
}; 
console.log( ninja.yell(4) == "hiyaaaa"); 
 
var samurai = { yell: ninja.yell }; 
var ninja = null; 
console.log( samurai.yell(4) == "hiyaaaa");

问题描述错误,已修改,直接来代码。第一段代码会出错,第二段代码可以执行,为什么呢,第二段代码给匿名函数一个名称了

PHP中文网PHP中文网2816 days ago246

reply all(2)I'll reply

  • 阿神

    阿神2017-04-10 16:33:44

    从前,有一间房子,长这个样子:

    {
        func:function(){
            console.log("this is a func");
        }
    }
    
    

    里面的 func 是一把椅子。

    你分配给了它一个门牌号,叫obj1,于是你可以通过 obj1.func 找到这把椅子。

    有一天,你又建了一栋房子,叫obj2,里面也有把椅子,叫func。它和obj1.func长得一模一样,因为它们就是指向同一把椅子。

    又有一天,你把obj1的门牌号丢了(obj1 = null;)。然而通过obj2.func,你仍然能访问`obj
    1`里的那把椅子。

    为什么呢?

    因为房子并没有丢啊,丢的只是门牌号而已。


    Update

    这又有所不同了,因为你在ninja.yell 中递归调用了ninja.yell,而ninja已经被你赋值为null了,自然访问不到。

    正确打开方式:

    ninja.yell(n-1) ---> arguments.callee(n-1)
    

    此为匿名函数递归正解

    reply
    0
  • 迷茫

    迷茫2017-04-10 16:33:44

    代码段1

    var ninja = {
      //1
      yell: function(n){
        return n > 0 ? ninja.yell(n-1) + "a" : "hiy";
      }
    };
    //2
    console.log(ninja.yell(4) == "hiyaaaa");
    
    //3
    var samurai = { yell: ninja.yell };
    //4
    var ninja = null;
    //5
    samurai.yell(4);

    代码1处 为对象ninja设置一个属性yell指向一个匿名函数表达式,并在匿名函数内部递归调用ninja.yell方法
    代码2处 递归调用成功 输出true,递归执行ninja.yell
    代码3处 新定义一个对象samurai,设置其属性yell指向ninja的yell属性,注意此时samurai的yell属性将指向一个函数对象,和其原来附着的对象ninja没有关系了,
    要理解这一点,可以尝试运行下面的代码

    var foo={
        name:"foo",
        fun:function(){
            console.log(this.name);
        }
    }
    
    foo.fun();//输出 foo
    var foo2=foo.fun;
    foo2();//undefined

    代码4处 将ninja指向为null,那么ninja对象将在某个时刻被JS虚拟机GC掉
    代码5处 执行时,JS引擎找到的ninja对象为null了,就会报错了TypeError: Cannot read property 'yell' of null,执行不下去

    代码段2

    //1
    var ninja = { 
      yell: function yell(n){ 
        return n > 0 ? yell(n-1) + "a" : "hiy"; 
      } 
    }; 
    //2
    console.log( ninja.yell(4) == "hiyaaaa"); 
    //3 
    var samurai = { yell: ninja.yell }; 
    //4
    var ninja = null; 
    //5
    console.log( samurai.yell(4) == "hiyaaaa");

    代码1处 为对象ninja设置一个属性yell指向一个有名字函数表达式,并在函数内部递归调用自己,注意这里的名字yell和ninjia的yell属性是2个不同的值哦
    作为函数名字的yell只在自己定义的函数体内有效,能被访问到。之外的任何地方都不能被访问
    代码2处 调用ninja.yell,在函数体内递归调用自己
    代码3处 行为同代码段A
    代码4处 将ninja指向为null
    代码5处 执行时,因为递归不依赖于调用的对象,故其能正常运行
    我们把代码调整下做个来测试一下

    var name=“global”;
    var ninja = { 
      name:'ninja',
      yell: function yell(n){ 
        console.log('I'm function in "+this.name);
        return n > 0 ? yell(n-1) + "a" : "hiy"; 
      } 
    }; 
    console.log( ninja.yell(4));//输出结果为 “I'm function in ninja” “I'm function in global” “I'm function in global” “I'm function in global” “I'm function in global”

    reply
    0
  • Cancelreply