一次JS前端面试经历:CVTE面试题与闭包陷阱解析

作者:异步漫步时间:2026-10-23 16:50:23浏览:247

本文记录了一次前往CVTE的前端面试全过程,涵盖一面与二面的核心面试题。重点解析了JS继承、闭包陷阱及内存泄漏问题,对比了Vue、React与Angular的选型差异,并探讨了Node.js特性与HTTPS原理。通过实际代码示例,详细阐述了利用let、立即执行函数及事件委托解决闭包引用问题的方法。

本文分享了一次JavaScript前端面试的真实经历,供读者参考。

近期公司进行战略调整,部门多位资深员工离职或被动离开,我所在的网易菠萝团队也被并入游戏运营中心。由于产品策划尚未落地,暂时缺乏具体需求,工作相对空闲。每天在公司看书、浏览知乎成为日常。目睹百人规模的事业部迅速缩减,令人感慨。甚至产生了参加省公务员考试的念头,已花费两三百元购买报名费和复习资料,但因对政治缺乏兴趣,资料至今未翻阅。日前,一位朋友告知其所在公司CVTE正在进行春季校园招聘,建议我尝试。CVTE在广东地区颇具知名度,以高于BAT的薪酬著称,传闻应届生月薪可达15K左右,且享有16至17薪。其校招宣传力度大,广东高校计算机专业学生多有所耳闻,其他省份可能较陌生,外界评价褒贬不一,感兴趣者可查阅知乎相关讨论。鉴于薪酬极具吸引力,我虽心动,但笔试时间已过且无法霸面。幸而朋友与HR相熟,且简历中提及NAT实习经历,最终顺利获得面试机会。


2月8日,我按惯例8:00起床(公司9:30上班)。打开手机,看到推荐我去CVTE的朋友发来多条微信,称已与HR沟通好,需在8:30前赶到黄村地铁站乘坐CVTE面试班车。这令我惊讶,因原本只是玩笑,没想到朋友如此认真。考虑到他费心争取的机会,放鸽子不妥,便匆忙穿衣穿鞋,未及洗漱,骑ofo直奔地铁站。广州近日春雨绵绵,早晨气温约10度,仅穿衬衫的我冻得发抖。好在8:25抵达黄村地铁站,从C出口出来即见白色CVTE班车。车上已有十余人,但因等待一位睡过头的候选人,司机直至8:50才发车。CVTE此举显得人性化,愿意为迟到考生等待20分钟。约40分钟后抵达广州罗岗CVTE园区,下车即见宏伟的CVTE大厦。此处纬度较高且多山,气温比学校低很多,令我全身颤抖。等待约2分钟后,HR引导我们上楼面试。等候区与面试区为同一会议室,设有2位HR和6位面试官(4人一面,2人二面)。刚落座,HR便叫4名同学上前面试,我第一个被叫到。尴尬的是,面试官询问手机尾号四位数字,输入多次未找到我的资料。HR随后想起我是无笔试直接面试,便将我拉至角落,安排另一同学先面试。HR询问是否带简历,我回答没有,随后通过微信添加好友,发送了旧版电子简历,并被要求回座位等待。


一面

约30分钟后,HR通知我进行第一轮面试。因天气寒冷,我全身发抖。面试官察觉后劝我放松,但我实为冷而非紧张,且仅穿一件衬衫。随后进行简短自我介绍,接着进入正式问答环节,以下是当时被问及的问题:

  1. JS有哪些手段可以实现继承?
  2. 说说JS的闭包?
  3. 用纯JS实现,点击一个列表时,输出对应的索引(不能用JQuery哦)
  4. CSS实现矩形按钮右边缘的中间有个往里凹的小半圆,如图:一面
  5. 为什么用vue而不用NG或者React?
  • 第一题较为简单,JS主要支持借用构造函数继承、原型链继承以及两者的组合。不熟悉者可参考《JavaScript高级程序设计》。
  • 第二题涉及闭包概念,建议自行查阅相关资料补充知识。
  • 第三题可能旨在考察对闭包的掌握程度。熟悉面试题的同学可能迅速作答,但经验不足者可能写出如下代码:

<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);
    }

另一种方法是经典书籍中提到的使用立即执行函数(IIFE)来切断闭包对外部变量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);

采用事件委托减少了监听器的绑定数量(仅对列表父元素监听),这种方法或许能加分。我当时即以此法作答,面试官对此解法感到意外,甚至一度怀疑console.log([].indexOf.call(lis, target))这段代码是否存在问题。直到我在其笔记本上直接运行验证,他才确认代码正确。

  • 第四题要求通过伪元素实现,由于我的CSS技能有限,仅知涉及CSS3的border-radius,但不熟悉伪元素的使用,故当场表示不会,至今仍未掌握。恳请CSS高手在评论区提供代码。

  • 第五题主要讨论框架选型。目前React是主流,CVTE团队也在使用React。面试官关注我为何选择Vue。我给出的理由是:Angular1的脏值检测性能较低且相对过时,Angular2尚不够成熟,React的JSX语法个人不太偏好,而Vue轻量且支持Jade模板(旧项目使用Jade模板,迁移相对容易)。然而,面试官连续质疑,称我使用Vue是否因中文文档齐全(暗示英语能力不足),并指出Vue不适合大型项目,最后一句更严厉:使用Vue是最愚蠢的选择。这让我内心十分不适。我认为框架无绝对优劣,各有存在理由,React、Angular、Vue各有所长,面试官的言论令人反感。第五题结束后,面试官示意面试结束,让我回座位休息。CVTE对考生招待周到,桌上备有水果、零食和饮料。因手机电量低,我边吃水果边观看其他考生面试。


二面

等待一个多小时后,进行第二轮面试。面试官约三十多岁,可能是前端组长或技术总监。主要问题如下:

  1. 说说JS的内存机制及垃圾回收机制
  2. 下面的代码有内存泄漏吗

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

二面问题难度适中,简要分析如下:

  • 第一题,基本类型(number, string, boolean, null, undefined, symbol)存储在栈中,引用类型存储在堆中。垃圾回收采用计数引用法(若两个对象存在循环引用,会导致内存泄漏,因为计数无法归零)。此处原文有误,误导读者,特此更正:JS使用的是标记清除法。原理可参考《JavaScript高级程序设计》第三版第78页。

  • 第二题,存在内存泄漏,这是闭包本身的问题。完全消除闭包导致的内存泄漏不现实,但采用以下方法可减少泄漏:

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;
  • 第三题为算法题,难度不大,读者可自行尝试实现,若遇到困难可在评论区求助,此处不贴代码。

  • 第四题考察计算机网络中TCP三次握手及HTTP请求头。HTTPS使用安全套接字层进行加密,可表示为HTTPS = SSL + HTTP。

  • 第五题,Node.js的特点是异步非IO阻塞、适合高并发场景,但不适合密集计算。

  • 第六、七题为主观题,可自由发挥。

因正值饭点,面试官急于用餐,未再提问。


二面结束已近中午12点。朋友鹏哥在门口等我一同前往食堂。CVTE提供自助餐,饭菜不错,但碗较小,未打多少便装满。食堂内员工热情,见我们背着书包知是面试者,便询问岗位、学历等。用餐时,鹏哥接到HR消息,称班车即将发车,需尽快用餐。因下午需回公司上班,在此偏远地点错过班车后果严重,故我不再进食,直接将饭菜倒掉,跑下楼赶班车。上车后司机立即发车,驶向香雪地铁站。再见,CVTE!


后记

首先评价此次面试水平。自去年9月至今,已大半年未参加任何面试,基础知识和面经宝典遗忘较多。原本无意面试,仅与鹏哥玩笑,他却帮忙联系HR安排妥当,故不能放鸽子。这是首次面试CVTE,传闻其算法要求高、面试难度大,但此次未涉及算法题,题目难度尚可接受。关于CVTE的评价,仅面试半天,难以定论。总体而言,从班车接送、面试期间提供水果饮料,到面试后安排食堂用餐,CVTE是一家不错的公司。至于面试结果,目前未知,可能通过也可能淘汰。

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容可查看本站专题:《JavaScript数学运算用法总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript数组操作技巧总结》、《JavaScript排序算法总结》、《JavaScript遍历算法与技巧总结》、《JavaScript查找算法技巧总结》及《JavaScript错误与调试技巧总结》

希望本文所述对大家JavaScript程序设计有所帮助。

作者最新文章