大家帮忙看下这个函数错误出在哪里了

var obj = {
  hello: function(n) {
    return obj.hello(n-1) + n;
  }
}
var obj2 = {hello: obj.hello};
obj = {};
console.log(obj2.hello(3));

阅读 2.6k
5 个回答

这是典型的引用丢失问题,两个对象引用了相同的函数,但函数引用自身的时候只是通过其中的一个对象,当obj置为空对象时,obj2对象的匿名函数仍然存在,但是obj1的属性已经不存在了,而这时再通过原有的obj.hello属性引用进行递归调用自身时,就会出现严重的问题。
解决方案建议将匿名函数的obj1显式引用改成this(函数上下文),这样obj2.hello()的this对象就是obj2,如此便可解决问题。
或者使用内联命名函数,将obj1对象定义如下:

var obj1 = {
  hello: function js(n) {
    return js(n-1) + n;
  }
}

因为你改变了obj的引用,所以在hello函数里面的引用的obj是那个新的obj
这个新的引用当然没有hello函数,自然就会报错。

但是,必须要注意的是,此时obj2引用的那个hello还存在。

obj已经赋值为空对象了,obj2里的引用的obj.hello自然也不存在了。

1.重新赋值obj对象了,新对象obj上没有hello()方法;
2.即使没有这段,你的hello()会栈溢出的,因为这是一个递归函数,就是不停地调用自己,n就侧漏了~~

以下内容纯属个人拙见,如有不妥,望不吝赐教,必将感激不尽

此函数考察内容有俩点:
1、引用类型数据的引用规则;2、函数的递归
分别阐述:
1、引用类型的引用,存储的是个地址,所以复制也是地址的复制,最后多个变量指向同一个引用类型数据。

例:var obj={"a":1};         //obj存储的是json对象地址
    var obj2=obj;            //obj2和obj存储统一地址,指向同一json对象
    console.log(obj2["a"]);    //1
    obj={};                    //obj是新引用类型数据的地址,obj2存储的原地址还存在
    console.log(obj2["a"]==1);    //true

总结:引用类型的多次赋值,不会导致覆盖,只会改变为新的地址,指向新的引用类型数据
所以,上面朋友说得对,obj2.hello函数还存在,因为函数也是引用类型数据

图片描述

这个函数存在是存在,但调用就会出错,因为其中用到了obj.hello(n-1);
用递归的arguments.callee(n-1)改进即可

图片描述

2、递归问题:

    函数递归调用,要设置边界,否则无限递归,超过内存
   ![图片描述][3]
    最完美递归:
        function recursion(n){
            if(n==1)return 1;
            return arguments.callee(n-1)+n;
        }
    
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题