欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

闭包是什么?

程序员文章站 2022-06-19 11:00:43
...

1.闭包是什么?
在JavaScript第三版程序设计中,闭包是这样定义的。
所谓的闭包就是有权访问另一个函数作用域中的变量的函数。
在JavaScript权威指南是这样说的:JavaScript函数是将要执行的代码以及执行这些代码作用域构成的一个综合体。在计算机术语里,这种代码和作用域综合称为闭包。
比如:

function test(){
	var num = 10;
	function closure(){
		console.log(num)
	}
}
test();

局部变量num+函数closure就构成了闭包;
为什么要嵌套函数呢?
因为需要提供局部变量。因此才把num放在函数中,如果没有外层函数就成了全局变量。

肯定有人说,那我听说闭包是需要返回一个函数的呀?正如下面的例子一样:

function test(){
	var num = 10;
	function closure(){
		console.log(num)
	}
	return closure;
}
test();

为什么要return closure呢?
不return closure;无法使用闭包。
不过也有别的方式。

function test(){
	var num = 10;
	closure = function(){
		console.log(num):
	}
}
test();
closure();

上面这个就是再没有return的情况下,也调用了closure这个函数。
test函数中,

var num = 10;
function(){
	console.log(num):
}

这个就构成了闭包。
2.闭包的作用
闭包的作用就是【间接的访问一个变量】。

  1. 可以读取函数内部的变量。
  2. 让这些变量始终保存在内存中。

3.闭包存在的问题
在IE9之前闭包会导致内存泄漏。这是由于IE9之前的版本对JScript对象和COM对象使用的是引用计数回收机制。

function assignHandler(){
        var element = document.getElementById("someElement");
        element.onclick = function(){
            alert(element.id);
        };
}

上面存在的问题就是element一直被引用这,引用次数至少为1。因此在引用计数的机制下内存是永远不能回收,因此可以手动null,代码如下:

function assignHandler(){
var element = document.getElementById("someElement"); var id = element.id;
        element.onclick = function(){
			alert(id);
		};
        element = null;
}

4.闭包的应用

1.索引值的问题
html

<ul id='ul'>
	<li>0</li>
	<li>1</li>
	<li>2</li>
</ul>

js

var oLi = document.getElementsByTagName('li');
for(var i=0;i<oLi.length;i++){
	oLi[i].onclick = function(){
		alert(i);
	}
}

我们无论点击哪一个li,alert的都是3。这是为何?
因为for循环已经遍历完。解决这个问题的方法很多,前面已经讲过好多种,现在我们主要用闭包解决这个问题。
第一种写法:

for(var i=0;i<oLi.length;i++){
	oLi[i].onclick = clickHandle(i);
}
function clickHandle(i){
		return function(){
			//这里的i其实就是函数外的局部变量
			alert(i);
		}
}

第二种写法:

for(var i=0;i<oLi.length;i++){
	(function(index){ //形参
		oLi[i].onclick = function(){
			console.log(index);
		}
	})(i) //实参
}

2.模拟私有变量

function MyObject(){
	var privateVariable = 10;
	function privateFunction(){
		return privateVariable;
	}
	this.publicMethod = function(){
		privateVariable++;
		return privateFunction();
	}
}
var obj = new MyObject();
obj.publicMethod(); //11

5.常见的闭包的面试题

var name = 'This Window';
var object = {
    name: 'My Object',
    getNameFun: function(){
        return () => {
            return this.name;
        }
    }
}
console.log(object.getNameFun()());//'This Window'
var object = {
    name: 'My Object',
    getNameFun: function(){
        var that = this;
        return function(){
            return that.name;
        }
    }
}
console.log(object.getNameFun()()); //'My Object'
function fun(n,o){
    console.log(o);
    return {
        fun:function(m){//[2]
            return fun(m,n);//[1]
        }
    }
}

var a=fun(0);////undefined
a.fun(1); //0
a.fun(2); //0
a.fun(3); //0
var b=fun(0).fun(1).fun(2).fun(3); //undefined,0,1,2
var c=fun(0).fun(1); //undefined,0,
c.fun(2);//1
c.fun(3);//1

最后一道面试题链接

相关标签: 闭包是什么?