javascript - js命名函数表达式的问题
PHP中文网
PHP中文网 2017-04-10 16:31:44
0
2
251
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中文网

认证高级PHP讲师

모든 응답(2)
阿神

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

{
    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)

此为匿名函数递归正解

迷茫

代码段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”
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿