腾讯js面试题3

深藏阁楼爱情的钟 2022-06-11 07:06 399阅读 0赞

该题难度系数: ★★★

考查的技术点: 1). DOM事件处理 2). 闭包

题目如下:

  1. /*
  2. 需求: 点击某个按钮, 提示"第n个"
  3. 问题: 下面的实现代码是否正确, 如果不正确, 请正确实现
  4. */
  5. var btns = document.getElementsByTagName('button')
  6. for(var i=0,length=btns.length;i<length;i++) {
  7. var btn = btns[i];
  8. btn.onclick = function () {
  9. alert('第'+(i+1)+'个');
  10. }
  11. }

单击每个按钮得到的运行结果均如图所示:

Center
根据结果,这明显是错误的啊。

那为什么会这样子呢?这明显不是我们想要的结果啊。因为i是一个全局变量(函数级变量),而3个内部函数都指向了同一个i,且最后一次i的赋值是3,所以点击弹窗时就是用同一个变量的。

那么接下来,我们该如何修改这段代码呢?目前想到几种方法:

第一种,用let代替var;

就是在for循环体里,把var换成let即可,如下所示:

  1. var btns = document.getElementsByTagName('button')
  2. for(let i=0,length=btns.length;i<length;i++) {
  3. var btn = btns[i]
  4. btn.onclick = function () {
  5. alert('第'+(i+1)+'个')
  6. }
  7. }

此时的结果就是我们要的结果了:

Center 1

那原理是什么呢?根据官方文档得知let就是声明一个块范围变量,即该变量的范围限于声明它的块中。就是let 允许把变量的作用域限制在块级域中,而var 申明变量要么是全局的,要么是函数级的,而无法是块级的,这就是let的精妙之处。i 变成块级域(也就是花括号中的块,每进入一次for的花括号就生成了一个块级域),所以3个内部函数指向了不同的i。

第二种,使用闭包。

那什么是闭包呢?一般两个条件,一是函数嵌套函数,二是函数可以访问另外一个函数的局部变量。简言之,有权访问另一个函数作用域内变量的函数都是闭包,这样就形成了一个闭包。

先来看个小案例:

  1. function fn1() {
  2. var a = 2
  3. function fn2 () {
  4. a++
  5. console.log(a)
  6. }
  7. return fn2
  8. }
  9. var f = fn1()
  10. f()
  11. f()

结果如下:

Center 2
分析如下:

Center 3

我们在浏览器debug调试一下这段代码,刚开始闭包里面a为2,closure就是闭包的意思。

Center 4

这时候输出的是3了,

Center 5

再接下来,就是输出4了

Center 6

这说明了,闭包可以实现局部变量的累加。但是要注意一点,不必要的闭包只会徒增内存消耗。

好的,言归正传,我们再来看下这道题目,用闭包如何实现,代码如下所示:

  1. var btns = document.getElementsByTagName('button')
  2. for(var i=0,length=btns.length;i<length;i++) {
  3. (function (i) {
  4. var btn = btns[i]
  5. btn.onclick = function () {
  6. alert('第'+(i+1)+'个')
  7. }
  8. })(i)
  9. }

得到的是正确的结果:

Center 7
原因是加了闭包之后,内存里面新增了3个不同的i,确切的说是4个,因为for里面也有一个i,3个内部函数指向了不同的i。

发表评论

表情:
评论列表 (有 0 条评论,399人围观)

还没有评论,来说两句吧...

相关阅读

    相关 2022面试

    2022【京东】面试真题: 1、哪些情况下的对象会被垃圾回收机制处理掉? 利用可达性分析[算][Link 1][法][Link 1],虚拟机会将一些对象定义为GCRoots

    相关 Java面试

    免费版:[腾讯 JAVA 面试题][JAVA] 一不小心收到鹅厂的面试邀请,想着鹅厂也还可以,帅哥美女也多,就去面试了。 ![watermark_type_ZHJvaWR

    相关 js面试2

    本题难度系数: ★★★ 考查技术点:  1). 变量提升  2). IIFE 3). 作用域与作用域链 4). 变量查找 var name = 'World!

    相关 08年面试

    1.1000瓶药水,其中至多有1瓶剧毒,现在给你10只小狗在24小时内通过小狗试药的方式找出哪瓶药有毒或者全部无毒(小狗服完药20小时后才能判断是否中毒) 答: 第一种: