之前看到一段代码,作者提了一个问题:代码中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 会被回收♻️了呢?
再如我把代码改一改:
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 得出:
迷惑了,这为啥又变成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 指向 windowobj.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
b函数运行完成,执行上下文就出栈了,但是由于其变量对象被外部引用,所以变量对象还是存在的,所以还能继续访问b函数里面的对象。
他回收不是说只留一个或几个属性,你这里打印的结果只代表chrome浏览器控制台的机制,和v8无关,其他浏览器应该也各有不同,比如firefox