<body>
<ul>
<li>test1</li>
<li>test2</li>
<li>test3</li>
<li>test4</li>
<li>test5</li>
<li>test6</li>
<li>test7</li>
<li>test8</li>
<li>test9</li>
<li>test10</li>
</ul>
<script>
var lis = document.querySelectorAll('ul li');
for(var i = 0, len = lis.length; i < len; i++) {
lis[i].addEventListener('click', function () {
console.log(i);
}, false);
}
</script>
</body>

你运行一下代码会发现,无论你点击哪个列表,控制台都是输出10。这是因为var声明的变量是函数作用域的,而不是块级作用域的。也就是说,for循环10次,每次都是改变同一个i,所以它的值会从0一直加到10。还有个问题是闭包导致的,闭包保存的是外部变量的引用,而不是值。也就是说,循环10次监听器创建了10 个闭包,它们里面的i引用的是同一个啊。所以全部都指向了10.
要解决这个问题有两种方法。一种是使用ES6的let来替代 var i = 0 里面的var, 因为let支持块级作用域。改成如下就正常了。

    for(let i = 0, len = lis.length; i < len; i++) {
lis[i].addEventListener('click', function () {
console.log(i);
}, false);
}

还有一种方法,就是很多经典书本都提到的,使用立即执行函数来切断闭包对外部变量i的引用:

    for(var i = 0, len = lis.length; i < len; i++) {
(function (i) {
lis[i].addEventListener('click', function () {
console.log(i);
}, false);
})(i)
}

当然啦,如果对闭包不是很熟练,还可以通过事件委托来避开这个陷阱哈,代码如下:

    var ul = document.querySelector('ul');
var lis = document.querySelectorAll('ul li');
ul.addEventListener('click', function (e) {
var target = e.target;
if(target.nodeName.toLowerCase() === 'li') {
console.log([].indexOf.call(lis, target));
}
}, false);

使用了事件委托,减少了监听器的绑定(只对列表的父亲元素监听),这种方法说不定还会加分呢。哈哈,我当时就是用这种方法来实现的,面试官可能觉得我的解法有点不寻常、顿时一脸蒙B,甚至还一度怀疑 console.log([].indexOf.call(lis, target)) 这段代码是不是有问题。直到后来我直接在他的笔记本跑了一遍,他才相信是正确的。

  1. 下面的代码有内存泄漏吗

    var user = {name: 'tom', age: 20, gender: 'male'}
    var test = document.getElementByid('test')
    test.onclick = function() {
    test.innerHTML = user.name;
    }
    // ...后面还有很多其他操作,最后把user对象释放掉
    user = null; // 释放对象
  2. 实现一个算法,寻找字符串中出现次数最少的、并且首次出现位置最前的字符
    如"cbaacfdeaebb",符合要求的是"f",因为他只出现了一次(次数最少)。并且比其他只出现一次的字符(如"d")首次出现的位置最靠前。
  3. http和tpc的关系,以及什么是https
  4. Node的特点(优点和缺点)
  5. 你在腾讯和网易实习期间学到的东西?
  6. 未来三年的职业规划

至于二面的问题都不是很难,下面简单的来看一下:

  • 第1题,基本类型(number, string, boolean, null, undefined, symbol)是在栈的,而其他的引用类型都是在堆的。垃圾回收是采用了计数引用法(如果两个对象之间存在循环引用时,会有内存泄漏,因为计数无法变为0 )

  • 第2题,有内存泄漏,这是闭包本身的问题。完全消除闭包的内存泄漏是不现实的,但是,如果采用下面的方法可以减少内存泄漏:

    var user = {name: 'tom', age: 20, gender: 'male'}
    var test = document.getElementByid('test')
    (function (name) {
    test.onclick = function() {
    test.innerHTML = name;
    }
    })(user.name);
    user = null;
  • 第3题算法题,也不很难,大家可以自己试试去实现 ,如果做不出来的再到评论求助啦,这里就不贴出代码了。

  • 第4题,考察了计算机网络的tcp三次握手以及http的请求头等。https是使用安全套接字进行加密的,可以说HTTPS = SSL + HTTP。

  • 第5题,Node的特点是异步非IO阻塞、适合高并发,但不适合密集型计算

  • 第6、7题都是主观题,可以随便吹一下水便好。

因为当时已经是饭点时间,面试官也有点急着去吃饭,就没有再问我问题了。

li点击弹出序号的更多相关文章

  1. jQuery之点击弹出图标环形菜单

    <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8&quo ...

  2. CSS3 页面中展示邮箱列表点击弹出发送邮件界面

    CSS3 页面中展示邮箱列表点击弹出发送邮件界面 代码: <!DOCTYPE html> <html> <head> <meta charset=" ...

  3. jQuery第二课 点击弹出一个提示框

    选择器允许您对元素组或单个元素进行操作. jQuery 选择器 在前面的章节中,我们展示了一些有关如何选取 HTML 元素的实例. 关键点是学习 jQuery 选择器是如何准确地选取您希望应用效果的元 ...

  4. JS 点击弹出图片/ 仿QQ商城点击左右滚动幻灯片/ 相册模块,点击弹出图片,并左右滚动幻灯片

    1, 点击弹出图片 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://w ...

  5. 工作当中实际运用(3)——js原生实现鼠标点击弹出div层 在点击隐藏

    function onmou(){ var divs=document.getElementById('kefuDV');//获取到你要操作的div if (divs.style.display==& ...

  6. 点击弹出 +1放大效果 -- jQuery插件

    20140110更新: <!doctype html> <html> <head> <meta charset="UTF-8"> & ...

  7. jquery---点击弹出层

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. form WebBrowser自动点击弹出提示框alert、弹出对话框confirm、屏蔽弹出框、屏蔽弹出脚本错误的解决办法

    针对WebBrowser控件中自动点击弹出框及禁用脚本提示问题得到如下几种实际情况的解决办法,绝对管用. 1.屏蔽弹出错误脚本 将WebBrowser控件ScriptErrorsSuppressed设 ...

  9. js点击弹出div层

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

随机推荐

  1. iOS 之 socket 与 http

    http连接:短连接,发送一次请求,服务器响应后连接就断开. socket连接:长连接,连接后长期保持连接状态.

  2. 3.3. 轻量级的迁移方式(Core Data 应用程序实践指南)

    持久化存储协调器会试着用新版的模板打开原来的持久化存储区,但是那是旧的模板,旧的格式,当然会出错.现在要做的就是迁移现有的持久化数据区,以便跟新模型匹配. 怎么进行迁移呢? 在什么时候进行迁移? 在向 ...

  3. HTML 5 服务器发送事件、Input 类型、表单元素、表单属性

    HTML5 服务器发送事件(server-sent event)允许网页获得来自服务器的更新. Server-Sent 事件 - 单向消息传递 Server-Sent 事件指的是网页自动获取来自服务器 ...

  4. C# winform DatagridView 的简单操作

    数据显示操作: dgBill.Columns[0].DataPropertyName = "key1"; dgBill.Columns[1].DataPropertyName = ...

  5. XMLSocket的bug

    "<cross-domain-policy>" "<site-control permitted-cross-domain-policies=\&quo ...

  6. Cocos2d-x 多分辨率支持

    最近遇到多分辨率支持问题,所以查了一些资料.将一些收获共享一下,以便自己和其他需要的朋友日后参考. 如果我要建立一个cocos2d-x项目,我的目标是支持iphone3G( 480, 320 ),ip ...

  7. C++中定义使用受限的类

    1.只能在堆上使用的类 栈上对象通过自动调用析构函数释放空间,将该类的析构函数定义为private就可以阻止其被自动调用,从而阻止在栈上使用该类的对象,为了避免资源泄漏问题,在堆上使用该类的对象时我们 ...

  8. Eclipse中TODO的分类,以及自动去除

    Window-Preference-Java-Compiler-Task Tags; 这里面进行TaskTag标签的定义,默认支持FIXME.TODO.XXX三种:优先级高的在taskview中 会显 ...

  9. window下redis的安装

    1.使用phpinfo()函数查看PHP的版本信息,这会决定扩展文件版本2.根据PHP版本号,编译器版本号和CPU架构,选择php_redis-2.2.5-5.5-ts-vc11-x86.zip和ph ...

  10. [C#]为微软ASP.NET官方教学视频增加字幕

    前言 Microsoft Virtual Academy提供了学习ASP.NET的大量视频材料.(注1) 由于视频服务器位于海外,国内浏览速度并不理想,幸好官方提供了视频的下载地址以及英文字幕文件. ...