JS闭包

最近在面试,发现面试官都非常喜欢问闭包相关的东西,所以写一篇文章整理一下自己的思路

一、作用域

在讲闭包之前必须说一下js作用域的问题;js在ES6之前其实是没有块级作用域这个概念的,但是有函数作用域这个概念,函数作用域可以访问父级作用域内部的变量,但是父级作用域无法访问函数内部的变量;

var firstName = '王';
function alertName(){
    var lastName = '诶诶';
    console.log(firstName);
};
alertName();//王
console.log(lastName);//Uncaught ReferenceError: lastName is not defined
二、闭包-例子1

闭包是指有权访问另一个函数作用域中变量的函数,创建闭包最常见的方式是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用域链,将函数内部的变量和方法传递到外部。

上代码:

for(var i=0;i<5;i++){
    setTimeout(function(){console.log(new Date,i)},1000);
}

这个的输出是:

Tue May 15 2018 11:28:25 GMT+0800 (中国标准时间) 5
Tue May 15 2018 11:28:25 GMT+0800 (中国标准时间) 5
Tue May 15 2018 11:28:25 GMT+0800 (中国标准时间) 5
Tue May 15 2018 11:28:25 GMT+0800 (中国标准时间) 5
Tue May 15 2018 11:28:25 GMT+0800 (中国标准时间) 5

这里涉及到的是异步代码的执行问题,为什么会输出5个5?因为函数执行的时候,i已经变成了5

那么如何输出0-1-2-3-4呢?这里就涉及到了闭包问题

var output = function(j){
    setTimeout(function(){console.log(new Date,j)},1000);
}
for(var i=0;i<5;i++){
    output(i);			
}

因为js基本类型的参数传递是按值传递,输出为:

Tue May 15 2018 11:35:17 GMT+0800 (中国标准时间) 0
Tue May 15 2018 11:35:17 GMT+0800 (中国标准时间) 1
Tue May 15 2018 11:35:17 GMT+0800 (中国标准时间) 2
Tue May 15 2018 11:35:17 GMT+0800 (中国标准时间) 3
Tue May 15 2018 11:35:17 GMT+0800 (中国标准时间) 4
三、闭包-例子2

如果我们要实现一个计数器,最简单方法:

var count = 0;
function increse() {
	count++;
	console.log('count is:',count);
}
increse();//count is: 1
increse();//count is: 2

那么如果要实现两个呢?写两次代码吗?no,我们可以用闭包了。

function counter() {
	var count = 0;
	function increse(){
		count++;
		console.log('count is:',count);
	}
	return increse;
}
var count1 = counter();
var count2 = counter();
count1();//count is: 1
count1();//count is: 2
count2();//count is: 1

在代码中,我们创建了两个独立的计数器counter1counter2,分别进行计数,互不干挠。代码看着有点奇怪,我们不妨拆分起来分析。

首先,我们来看看counter

  • 创建了一个局部变量counter
  • 创建了一个局部函数increse(),它可以对count变量进行加1操作。
  • 将局部函数increse()返回。注意,返回的是函数本身,而不是函数调用的结果。

看起来,counter()函数与我们最初定义的计数器非常相似。唯一的不同点在于:counter()将计数器封装在一个函数内,于是我们将它称作闭包。闭包的神奇之处在于。每次使用counter()函数创建计数器时,都会创建一个对应的count变量。并且,返回的increment函数会始终记住count变量。更重要的是,这个count变量是相互独立的。比如,当我们创建2个计数器时,每个计数器都会创建一个新的count变量。

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页