JS核心知识点梳理——上下文、做用域、闭包、this(下)

clipboard.png

引言

前面两篇文章介绍了上下文、做用域、闭包、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

六、如下代码的功能是要实现为5个input按钮循环绑定click点击事件,绑定完成后点击一、二、三、四、5五个按钮分别会alert输出0、一、二、三、4五个字符。(腾讯)

请问以下代码是否能实现?
若是不能实现那么如今的效果是什么样的?
应该作怎样的修改才能达到咱们想要的效果,并说明原理?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组:

这类题目严格按上篇文章的分析思路,不复杂,就是麻烦一点。不要在脑子里想,每步的结果用纸和笔演算下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
相关文章
相关标签/搜索