关于闭包的一些提问

之前看到一段代码,作者提了一个问题:代码中f引用了变量d,同时f被外部变量a引用,所以形成闭包,导致变量d滞留在内存中。那么变量c是否也滞留在内存中呢?

var a
function b() {
  var c = new String('1')
  var d = new String('2')
  function e() {
    console.log(c)
  }
  function f() {
    console.log(d)
  }
  return f
}
a = b()

我执行代码查阅[[Scopes]]发现 c 变量确实滞留在闭包内,这是因为函数内闭包共享。那么我有个疑惑,为何变量 c滞留在缓存中,而函数 e 会被回收♻️了呢?
image.png

再如我把代码改一改:

var kk = 'hello'
function b() {
  var c = new String('1')
  var d = new String('2')
  function e() {
    console.log(c)
  }
  function f() {
    console.log(kk)
  }
  return f
}
var  a = b()
console.dir(a)

此时再去打印 a 得出:
image.png

迷惑了,这为啥又变成c 滞留呢,d去哪了?还有这个 f 函数为啥没成为闭包呢?是不是说明了 成为闭包的条件是内部函数必须跟外部函数关联,而跟全局变量关联的时候并不能成为闭包呢?

还有一个提问:为什么 getName中的内部函数打印出来的 this 指向 window 呢?

var object = {
     name: "object",
     getName: function() {
        console.log(this,'000000')
        return function() {
             console.info(this,'1111')
        }
    }
}
var a = object.getName()
console.log(a) //指向 object 对象
var b = a()
console.log(b) //指向全局的 window

暂时还没能总结陈词,看了一篇帖子对我提出的函数调用解释是这样子的👇,(不知道得出来的总结对不对,下面是我的理解,如果有异议那就戳我并且给点纠正方案给我吧~~Thanks♪(・ω・)ノ):
https://zhuanlan.zhihu.com/p/...

  • js 中的函数调用形式:
func(p1, p2) 
obj.child.method(p1, p2)
func.call(context, p1, p2)

所以getName中的内部函数打印出来的 this 指向 window
obj.child.method.call(obj)

ok,加深难度,回答一下下面的这个函数调用解析情况:

function test (){
    console.log(this,'000000')
    var obj = {
    a:function (){
       console.log(this,'1111')
       return function(){
            console.log(this,'22222')
        }
    }
    }

return obj
}

test().a()()
//打印结果
// window{...},00000
// {a:f}, 11111
// window{...},22222

同样根据上面得出的解析是:
fn.call(obj).child.method.call(obj,afunction).call(undefind)
所以最里面的函数调出出来指向的 this 是指向 window,那么如果我们想在最内部的函数能够获取到上面的 obj 中的变量,方法等内容时可以这么写:

function test (){
    console.log(this,'000000')
    var obj = {
    a:function (){
       console.log(this,'1111')
        var that = this
       return function(){
            console.log(that,'22222')
        }
    }
    }

return obj
}

test().a()()

//{a:f}, 11111
//{a:f}, 22222

得出结论:(结论有点粗糙,在总结更加官方的解释中。。。欢迎贴出您的总结陈词)
this的指向完全取决于函数调用的位置,a 函数调用时,他的调用位置是 obj.child.method.call(obj)的调用方式,而最内层的函数调用时,因上方的 a 函数已经调用完毕,函数不通过对象调用时,this就指向window

阅读 1.3k
1 个回答

b函数运行完成,执行上下文就出栈了,但是由于其变量对象被外部引用,所以变量对象还是存在的,所以还能继续访问b函数里面的对象。

他回收不是说只留一个或几个属性,你这里打印的结果只代表chrome浏览器控制台的机制,和v8无关,其他浏览器应该也各有不同,比如firefox

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题