JS 经典闭包面试题

1.带参闭包问题

function foo(x) {
    var tmp = 3;
    return function f2(y) {
        alert(x + y + (++tmp));
    };
}
var bar = foo(3); // bar 现在是一个闭包
bar(10);

:首先执行var bar = foo(3);那么foo就执行了,参数3也传进去了,但是执行完毕后,tmp变量以及参数x就已经被释放回收了吗?
并没有,因为返回值里面还等待使用这些变量,所以此时,foo虽然执行了,但是foo的变量并没有被释放,在return中等待继续使用这些变量,这时bar就是一个闭包。

2.事件闭包问题
例:很多元素绑定一个点击事件
点击每个按钮时拿到当前按钮所对应的索引值
CSS样式如下:

<button class="btn">按钮</button>
<button class="btn">按钮</button>
<button class="btn">按钮</button>
<button class="btn">按钮</button>
<button class="btn">按钮</button>
<button class="btn">按钮</button>
<button class="btn">按钮</button>

首先看拿不到在for循环里当前对象的i值的写法:

var btn = document.getElementsByClassName("btn");
for (var i = 0; i < btn.length; i++) {
    btn[i].onclick = function () {
        alert(i);
    }
}

注:网页初始化时,每个按钮的事件都已经绑好了,用户触发都是后续触发的,后续触发说明事件有了,事件有了说明for循环执行完成,i就已经拿到最大值
问题:怎样在for循环里拿到当前对象的i值
解决:索引对索引
写法一:参数的传递

var btn = document.getElementsByClassName("btn");
for (var i = 0; i < btn.length; i++) {
    //参数的传递  桥梁
    btn[i].index = i;
    btn[i].onclick = function () {
        alert(this.index);
    }
}

写法二:自执行函数的闭包 自执行函数的参是后面跟括号里的参数传的

var btn = document.getElementsByClassName("btn");
for (var i = 0; i < btn.length; i++) {
    (function (x) {
        btn[i].onclick = function () {
            alert(x);
        }
    })(i);  //这个i是for循环的i
}

:for循环每一次都执行一个自执行函数,每一次变量i被当做参数传到IIEF(自执行函数)中去,那么这个IIEF中创建了一个变量参数x,然后元素节点btn绑定了一个onclick事件,执行函数里面需要用到这个参数x,但是你又没点,那么这个变量x就没有被清理,就一直在参数里面被保存着,每一个IIEF都做一样的事情,所以这个时候就产生了闭包,变量x并没有被回收,依然在等待使用。

3.面向对象

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

4.首先解释arguments
arguments指当前函数的参数列表,类似于数组的集合,使用索引值取;
arguments.length返回当前参数列表的长度

function f1(a, b, c) {
    console.log(arguments[0]);  //4
    console.log(arguments.length);  //3
}
f1(4, 5, 6);

例:

function f1(a, b, c) {
    /*arguments 是当前函数的参数列表  类似于数组的集合  使用索引值来取*/
    console.log(arguments.length);
}
f1(1, 2, 3);
var sum = function () {
    var cache;
    if (arguments.length === 1) {
        cache = arguments[0];  //如果arguments对象的长度为1,也就是参数只有1个时,将这个参数赋值给cache,暂存
        return function (number) {  //返回一个函数,函数里的参数(也就是第二个括号里的参数)与之前第一个括号里的参数相加
            return cache + number
        }
    } else {
        return arguments[0] + arguments[1];  //如果arguments对象的长度不为1,那么两个参数相加
    }
}
console.log(sum(2, 3));  //5
console.log(sum(2)(3));  //5
  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值