闭包面试题总结

题型一

for (var i = 1; i <= 5; i++) {
			setTimeout( function timer() {
				console.log(i);
			}, 1000 );
		}
后台打印了5个6
分析:

首先这样的结果需要从JS的执行机制说起。JS是单线程环境,也就是说代码的执行是从上到下,依次执行。这样的执行称为同步执行。因为种种不要浪费和节约的原因。JS中引进了异步的机制。在这段代码中,哪个是同步哪个是异步呢?for循环是同步代码,而setTimeout中的是异步代码。那么JS碰到这个有同步和异步的情况下会先从上到下执行同步代码,碰到异步的代码会将其插入到任务队列当中等待。而setTimeout是延时,也就是说碰到setTimeout这个异步的代码块会根据它里面的第二个参数:延时时间来将代码插入到任务队列当中,比如上面这段代码中,第二个参数延时时间是0,也就是说执行到它的时候会在1000ms之后将它插入到任务队列当中。同步代码都执行完成之后,那么JS引擎就空闲了,这个时候就轮到任务队列中的异步代码依次加载了。

这是上面这段代码的答案的一半。另一半就来自于作用域,作用域是变量等资源的作用范围。在这段代码中准确的说是作用域链的问题,当同步代码执行完毕开始执行异步的setTimeout代码时,setTimeout中需要一个变量 ---i---,而执行的时候在当前的作用域中开始找,找不到变量i的定义,这个时候就把创建这个函数的作用域作为当前作用域,再次寻找,创建这个函数的作用域就是全局作用域,也就是找到了for循环中i,找到了之后就结束寻找变量i的行程。由于这个时候的i是全局的,而且人家已经变为了最终形态:6,setTimeout找到的就是这个i=6;所以就输出了6,下面的4次setTimeout 的执行都是类似,所以结果都是6;


那么怎么样才能输出1、2、3、4、5呢?

因为5个定时器所打印出来的是同一个i变量,所以想要实现输出不同的数字,就需要把每个定时器所访问的变量独立起来,这就用到了JavaScript的闭包。闭包用途很多,可以很好地区分开各个作用域,避免变量的混淆,但是滥用闭包也会导致性能问题。那么通过下面的修改就可以了;

 for (var i = 1; i <= 5; i++) {
			(function(i){
				setTimeout( function timer() {
				console.log(i);
			}, 1000 );
			})(i)
		}

或者也可以用ES6的let,

for (let i = 0; i <= 5; i++) {
			setTimeout( function timer() {
				console.log(i);
			}, 1000 );
		}

题型二

var name = "world";
     (function () {
     	if (typeof name == 'undefined') {
     		var name = 'yang';
     		console.log('Hello ' + name)
     	} else {
     		console.log('Hello ' + name)
     	}
     })()

上面的代码相当于

var name = "world";
     (function () {
     	var name;
     	if (typeof name == 'undefined') {
     		var name = 'yang';
     		console.log('Hello ' + name)
     	} else {
     		console.log('Hello ' + name)
     	}
     })()

所以答案是:Hello yang

题型三

function fun(n,o) {
     	console.log(o)
     	return {
     		fun:function(m){
     			return fun(m,n);
     		}
     	};
     }
     var a = fun(0);  //undefined
     a.fun(1);  //0
     a.fun(2);  //0
     a.fun(3);  //0
function fun(n,o) {
     	console.log(o)
     	return {
     		fun:function(m){
     			return fun(m,n);
     		}
     	};
     }
     var b = fun(0).fun(1).fun(2).fun(3); //undefined 0 1 2
     function fun(n,o) {
     	console.log(o)
     	return {
     		fun:function(m){
     			return fun(m,n);
     		}
     	};
     }
     var c = fun(0).fun(1);  //undefined 0
     c.fun(2); //1
      c.fun(3); //1

题型四




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值