是只要是函数嵌套函数,不管是被嵌套函数是否引用了外部函数的局部变量就是闭包,还是内部函数必须return出去之后才形成闭包?
1.第一个例子
// #1
function outer(a,b){
var c = 999;
function inner(){
console.log(a,b,c);
}
inner(); // 直接调用了内部函数,并没有return出去,这是闭包么?
}
/*----------------------分割线----------------------------*/
// #2
function outer(a,b){
var c = 999;
// 这种情况下,inner没有引用外部outer的变量
function inner(){
var d = 2;
var e = 3;
console.log(d+e);
}
inner(); // 直接调用了内部函数,并没有return出去,这是闭包么?
}
/*----------------------分割线----------------------------*/
// #3
function outer(a,b){
var c = 999;
// 这种情况下,传入的str如果是变量名的话,就会引用outer内的变量
function inner(str){
console.log(eval(str));
}
return inner;
}
var inner = outer(1,2);
inner("a"); // 1
inner("b"); // 2
inner("c"); // 999
如果只要是函数嵌套函数就是闭包的话,那么如果没有return inner出去的话,也就不会出现在外面引用outer函数的局部变量了(#2),那么outer函数执行过后,即使outer内部的局部变量存在于内存中,也没有程序会访问到了,那么,GC会销毁outer内部的局部变量么?但是#3这种情况下,inner虽然没有显式地调用outer的局部函数,但是存在这种可能性,例如
inner("a")会访问outer的局部函数a,那么显然这种情况下,GC肯定不会销毁outer。。
哎呀,反正是很迷惑,请各位大牛给个醍醐灌顶的感觉吧???
2.第二个例子
function outer(a,b){
var c = 999;
function inner(){
console.log(a,b,c);
}
return inner; // 把内部函数return出去,就形成了闭包,这点儿我肯定
}
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
我们通常所说的闭包(之所以说“通常”,是因为从某种意义上来说,js中所有的函数都是闭包 —— 因为函数内部能够访问到外部的变量。但我们只关心下面所说的“闭包”),它的形成有两个要素:
闭包引用外部函数变量对象中的值;
在外部函数的外部调用闭包。
理解闭包的关键在于:外部函数调用之后其变量对象本应该被销毁,但闭包的存在使我们仍然可以访问外部函数的变量对象。
闭包闭包!了解更多
你可以这么认为,所有程序分配的变量都是不会回收的,所以只要你能想办法访问到就可以,不用去关心GC。GC设计的目的就是回收那些你绝对不用的内存。既然如此我们为什么要当作GC是存在的呢,在我们编程的时候即使当作GC是不存在的,对我们也没有什么影响。
闭包的可以实现类似私有成员的变量。
闭包可以防止变量名污染全局变量空间,就是说可以在一定程度上防止变量重名的问题。
内存泄漏:这个到不至于,这个在js里的意思是,使用闭包的时候特别容易不小心创建了过多的变量(而GC又无法回收),然后就导致内存耗尽。
题主通篇没有提作用域这个关键词。
理解闭包,先把作用域这块好好理解下。
a嵌套b,
a的作用域包含了b的作用域
b就可以引用a里的内部变量
但是a不能引用b里边的内部变量
闭包就是能够读取其他函数内部变量的函数。
所以闭包并不是像你说的由什么return 去触发的。
b在创建的时候,就有了可以使用a作用域的变量的权力
b这时候就是个闭包,也可以把闭包理解为‘定义在一个函数内部的函数,它是将函数内部和函数外部连接起来的一座桥梁’
闭包的好处,显而易见,比如创建个对象,可以封装一些特权方法访问私有属性。
也可以创建内部变量,不能在外部进行随意更改。
内存泄露问题,我理解不深,随便说两句,抛砖引玉
如果闭包也就是现在的b,b引用了a的内部变量的话。
如果需求需要b一直存在,也就导致a的内存也一直存在不会被回收,所以存在内存泄漏问题。
书上好像有过一个例子,内存泄露的情况:
改成这种,就不会内存泄露