前面两篇文章介绍了上下文、做用域、闭包、this。这里我精心挑选了一些特别经典的面试题(不按期更新,跪求收藏)。相信经过这些题目能让你彻底通关JS三座大三中的之一。javascript
这类题目仍是挺简单的,我总结了几个要注意的地方
1.有没有闭包
2.若是有闭包,看建立了几个闭包。换句话说,是在一个闭包内直接操做仍是操做完一个闭包,再建立一个新的闭包继续操做
3.注意数据的归属,即数据存放在哪一个上下文环境
java
var n=0; function a(){ var n=10; function b(){ n++; console.log(n); } b(); return b; } var c=a(); c(); console.log(n); //11 12 0
var a=9; function fn(){ a=0; //若是这里是var a = 0 ,答案是多少 return function(b){ return b+a++; } } var f=fn(); console.log(f(5)); console.log(fn()(5)); console.log(f(5)); console.log(a); // 5 5 6 2 // 若是是var a = 5 5 6 9
var ary=[1,2,3,4]; function fn(ary){ ary[0]=0; ary=[0]; ary[0]=100; return ary; } var res=fn(ary); console.log(ary); console.log(res); // [0,2,3,4] [100]
function fn(i) { return function (n) { console.log(n + (i++)); } } var f = fn(10); f(20); fn(20)(40); fn(30)(50); f(30); //30 60 80 41
var i = 10; function fn() { return function (n) { console.log(n + (++i)); } } var f = fn(); f(20); fn()(20); fn()(30); f(30); //31 32 43 44
请问以下代码是否能实现?
若是不能实现那么如今的效果是什么样的?
应该作怎样的修改才能达到咱们想要的效果,并说明原理?es6
<div id="btnBox"> <input type="button" value="button_1" /> <input type="button" value="button_2" /> <input type="button" value="button_3" /> <input type="button" value="button_4" /> <input type="button" value="button_5" /> </div> <script type="text/javascript"> var btnBox=document.getElementById('btnBox'), inputs=btnBox.getElementsByTagName('input'); var l=inputs.length; for(var i=0;i<l;i++){ inputs[i].onclick=function(){ alert(i); } } </script>
1.不能实现
2.由于js没有块做用域,因此公用的外层做用域的i,当点击触发函数的时候 ,应当注意外层的i是5了,因此所有打印5没毛病
3.
解决思路1:没有块做用域我就用es6的let造成块做用域面试
for(let i=0;i<l;i++){ inputs[i].onclick=function(){ alert(i); } }
解决思路2:每次绑定的时候i其实都是正确的,我能不能用另一个变量将每次的i存起来呢?闭包
//这样行吗? for(var i=0;i<l;i++){ inputs[i].onclick=function(){ var num = i alert(num); } } //这样仍是不行,由于回调函数定义的时候并不会执行,因此当var num = i 执行的时候i已经等于5了
那么我应该让回调函数定义的时候里面的代码能当即执行,接收到参数0,1,2,3,4函数
for(var i=0;i<l;i++){ inputs[i].onclick=(function(){ var num = i alert(num); })(i) } //这样也有问题i传递进去了,可是里面核心代码定义也执行了,我想让它点击的时候再执行
for(var i=0;i<l;i++){ inputs[i].onclick=(function(){ var num = i return function (e) { //注意这个时候e是啥,是点击的事件 console.log(num) } })(i) } //这样就没毛病了,返回一个方法,不会当即执行,i传进去了,给了num,因为有闭包,又不会被销毁
还能怎么优化?既然i能传进去,我为啥还要而外用个变量保存呢?优化
for(var i=0;i<l;i++){ inputs[i].onclick=(function(x){//x是形参,因为闭包存在,上下文不销毁 return function () { console.log(x) } })(i) }
这类题目严格按上篇文章的分析思路,不复杂,就是麻烦一点。不要在脑子里想,每步的结果用纸和笔演算下
this
var num = 10; var obj = {num: 20}; obj.fn = (function (num) { this.num = num * 3; num++; return function (n) { this.num += n; num++; console.log(num); } })(obj.num); var fn = obj.fn; fn(5); obj.fn(10); console.log(num, obj.num); //22 23 65 30