2018前端面试题集锦

848 阅读12分钟

就题目谈答案不是目的,了解更深层次的东西才是根本。不仅要知道,还要答的漂亮。

1.描述盒子模型。

2.两个并列的display:inline-block的子元素之间的为什么有空隙。

  • 答案很简单,这些空隙就是空白符。
  • 怎么去掉这个空白符呢,就是把父元素的样式设为font-size:0;别忘了子元素自己也要设置字号,不然就会继承父元素的字号变成0了。

3.举几个行内元素的例子。

  • b, big, i, small, tt
  • abbr, acronym, cite, code, dfn, em, kbd, strong, samp, var
  • a, bdo, br, img, map, object, q, script, span, sub, sup
  • button, input, label, select, textarea

4.cookie、localStorage、sessionStorage的区别。

  • Http cookie,通常叫做cookie,用于在客户端存储简单的会话信息,长度不超过4095B,由名称路径失效时间安全标志组成。需要注意的是,除了名值对是在Request Headers中一起发送给服务器的,其他的只有Response Headers才会有,是服务器给浏览器的指示。
  • sessionStorage对象用于存储特定于某个会话的数据,浏览器关闭数据就会消失,他可以跨越页面刷新而存在。可以用getItem(), setItem(), removeItem() 等去操作数据。
  • localStorage对象用于储存持久的大量的客户端数据,只有同域名同协议通端口的页面才可以访问。

5.如何实现浏览器的跨tab通信,就是两个Tab页面,在第一个里面比如点击了一下,然后另一个Tab页面会有相应的反应。

  • 这个问题就是上面的客户端存储问题涉及到的一个用法,对sessionStorage和localStorage的操作会触发storage事件,通过监听这个事件就可以知道其他的同源的页面对sessionStorage或者localStorage的操作。

6.css实现三角形,不是svg那些。

7.实现元素的垂直水平居中。

8.position定位的四种属性,分别表示什么。

9.如何解决移动端适配的问题。

10.js的基本数据类型有哪些,ES6新增了什么?

  • 基本数据类型:Undefined,Null,Boolean,Number,String,Symbol(ES6新增,一种数据类型,它的实例是唯一且不可改变的);
  • 引用数据类型:Object;
  • 基本数据类型和引用数据类型的区别:在将一个值赋给变量时,解析器会去确定这个值是基本类型值还是引用类型值。基本数据类型是按值访问,可以操作保存在变量中的实际的值;而引用数据类型是保存在内存中的对象,JavaScript不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间,在操作对象时,实际上是在操作对象的引用而不是实际的对象,为此,引用类型的值是按引用访问的。引用是一个指向对象实际位置的指针。

11.跨域请求的方法,重点问了jsonp的实现原理。

12.如何按需加载js,就是满足某个条件就加载这段script,不需要就不加载。

举个栗子吧:

<body>
    <div onclick='loadjs()'>click me!</div>
    <div onclick='loadjs2()'>click me!</div>
</body>
<script>
    // 期望的状态。
    function loadjs() {
        var script = document.createElement('script');
        script.src = '//cdn.bootcss.com/jquery/1.12.4/jquery.min.js';
        document.getElementsByTagName('html')[0].append(script);
    }
    // 对比。
    function loadjs2() {
        document.write('<script src="//cdn.bootcss.com/jquery/1.12.4/jquery.min.js" type="text/javascript" charset="utf-8" async defer><\/script>');
    }
</script>

13.bind、call、apply的区别及使用场景。

14.事件传播会经过哪些阶段。然后接着问,事件捕获的原理是什么,为什么绑定在父元素的事件,在子元素触发。addEventListener第二个参数的默认值是什么。

  • 三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。
  • 当时说的是子元素从父元素那里继承了这个事件。
  • addEventListener的第二个参数是默认值是false,true表示在事件捕获阶段调用事件处理程序,false表示在事件冒泡阶段调用事件处理程序。

15.描述什么是原型链,prototype和__proto__的区别是什么。

  • js中每个对象都有一个私有属性(称之为[[Prototype]]),它指向创建它的函数对象的原型对象(prototype)。
  • 该 prototype 对象又具有一个自己的 prototype, 层层向上直到一个对象的原型为null。根据定义,null没有原型,并作为这个原型链中的最后一个环。其实原型链的顶端就是Object.prototype.proto,也即为null。
  • [[Prototype]]就是主流浏览器所说的__proto__。

16.let、var的区别,一条考烂了的题。

for(var i = 0; i < 10; i ++) {
    setTimeout(function(){
        console.log(i);
    },0);
}

会输出什么,如何让他输出0-9呢,如果回答了把var换成let,紧接着会问,为什么换成let就能输出0-9,原理是什么。

  • 会输出10。这里会输出10的原因是,setTimeout是异步任务执行,会被加入到任务队列中,等执行栈中的同步任务都执行完毕,任务队列中的异步任务才会被调用,这是影响因素之一;影响因素二就是var没有块级作用域,所有的i都指向同一个引用,而i的累加会先于异步任务执行,再次之前i已经变成了10;
  • 这个使用let,每一次循环会生成独立的执行环境,每一个i指向不同的引用,所以最终打印出来就是不一样的。

17.数组去重。

// Set
function unique(arr) {
    return [...new Set(array)];
}

算了,还是看这个吧。

18.编写一个会被两次调用的函数,如add(2)(3),结果是5。

function add(a) {
    return function(b) {
        return a + b;
    }
}

19.实现斐波那契数列。

// 递归实现,看上去比较优雅。
function Fib(n) { 
    return n < 2 ? n : (Fib(n - 1) + Fib(n - 2)); 
}
// for循环非递归实现
function fib(n) {
    if (n < 2) {
        return 1;
    }
    var a = 1, b = 1;
    for (var i = 2; i < n - 1; i++) {
        b = a + b;
        a = b - a;
    }
    return a + b;
}

20.实现一个求算术平方根的函数。

21.不使用循环实现数组元素的累加(递归和非递归两种实现)。

22.ES6中的.repeat()方法的polyfill。

23.返回数组中包含aa的元素['aaa','abc','bbc','dadadeq',['aaa','bbb','ccc',['aaa','bac','ccc','ewee',['aaa','asasa']]],使得返回值为['aaa','aaa','aaa','aaa'],差不多就这个意思,只不过里面具体的元素不是这些。

24.vue的不同生命周期的函数钩子?

// 源码直接给出
export const LIFECYCLE_HOOKS = [
    'beforeCreate',
    'created',
    'beforeMount',
    'mounted',
    'beforeUpdate',
    'updated',
    'beforeDestroy',
    'destroyed',
    'activated',
    'deactivated',
    'errorCaptured'
]

25.浏览器性能优化。

26.控制缓存问题。

27.如何避免用户看到未渲染完成的页面。

28.如何解决移动端1px被渲染为2px的问题。

  •   <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" /> 
      和 transform: scale(0.5) 来处理 
    
  •   <meta name="viewport" content="width=device-width,initial-scale=0.5,minimum-scale=0.5,maximum-scale=0.5,user-scalable=no" />
    
  • 上面两种是针对*2的屏,如果有*3的屏,0.5就会是0.3333333
  •   //更加通用的方法
      var dpr = window.devicePixelRatio;
      meta.setAttribute('content', 'initial-scale=' + 1/dpr + ',maximum-scale=' + 1/dpr + ', minimum-scale=' + 1/dpr + ',user-scalable=no');
    

29.知道SEO吗,用了vue或者react之后怎么做SEO,问vue还是react视简历而定,你写的什么你会用什么,他就问什么。

  • 服务器端渲染的页面做SEO的过程,在<meta><title>标签里面设置要设置合适的关键词,关键词在整个页面里面出现的几率为5%-8%比较合适。
  • 在根目录建一个sitemap.xml
  • 和其他网站交换友链
  • 如果使用了vue,尤大大也说了,用了vue也不一定要写成SPA,如果不是SPA而是而是服务器端渲染的,那么SEO还是上面的,如果既想要SPA的强交互性又想要SEO,可以使用SSR。

30.如何评价各种前端技术栈,好大的题目,怎么回答,见仁见智了。

  • 这个题我感觉按照31的思路去说也是可以的。

31.vue、react、jquery等的优劣对比。

  • 这种题目单纯的对比优劣可以参考的帖子很多。
  • 但是选择什么最终要服务于要实现什么,选择最适合自己网站的技术栈才是根本,不妨从这个角度去谈优劣对比更有说服力,毕竟所谓优劣更多都是相对而言的。
  • 那就先从单页面应用和多页应用说起吧,参考
  • 简而言之,如果追求强交互性选择SPA,如果对SEO要求比较高、交互性需求比较一般可以使用MPA,如果不管怎么样既要交互性又要SEO,vue给出的解决方案就SSR。
  • 然后从几个角度去谈具体的优劣:DOM操作、虚拟DOM、响应式、组件化、性能、学习成本等等方面分别谈一谈各有优劣。
  • 然后说到SPA说到性能,可能会谈的首屏加载太慢的问题,这算是自己给自己挖坑吗,除了基本的CDN加速,压缩静态资源,按需引入组件,要么就是 服务器端渲染。
  • 参考:Vue SPA 首屏加载优化实践vue、react、angular三大框架对比 && 与jQuery的对比

32.看你项目里面jq用的挺多的,读过源码吗?

我:没有。

好了,今天的面试结束了,回去吧。

后来又是一场问到这个问题,我就回答了“稍微看了一点”,然后就问,那你对jq的架构设计或者底层原理知道什么,说说看。

emmm....,问的倒是一点都不客气。

33.这是一个比较personal的问题,一个聊天室,我用了ajax轮询实现的消息的获取,当时是局限于后端不支持websocket,所以没能使用这个更好的技术实现。于是此处引出两个问题,1)ajax轮询如果某一次请求的返回结果比较慢,甚至比后一次的返回结果还晚,如何避免因为这种延时造成消息显示的混乱;2)了解过websocket吗,如果用它要怎么去实现?

34.一般你是怎么写babel配置文件的让ES6的代码能够兼容各种老的浏览器。

35.this作用域。

36.闭包肯定少不了了。

37.如何解决点击穿透问题。

  • touchstart 300ms之后会触发click时间,在300ms之内,如果上面的一层已经消失,click就会作用到下面一层,如果下面一层恰好可以点击,就会发生点击穿透。
  • 解决方法,只用touch事件,如果全局没有click事件,就不会触发后续的click事件了。
  • 只用click事件会导致任何交互都有300ms的延时,体验不太好。
  • touch事件350ms之后再隐藏弹层,那么click就不会触发到下面的元素了。
  • 这篇提供的其他方法作为参考吧

38.ios的scroll问题怎么解决。

39.移动端适配如果使用rem的话,rem的根节点的font-size的值通常怎么计算。

  • rem = document.documentElement.clientWidth * dpr / 10
  • 除以10是为了方便计算,其实可以是任何值。
  • 个人觉得这个只是一种约定俗成的办法,也不是非这样不可吧。
  • 参考

40.列举一些用到的css3的属性,着重问了animation的使用方法。

41.ES6的箭头函数与ES5的function除了this的不同点,还有什么不同点。

  • 箭头函数不可以当作构造函数。
  • 箭头函数不存在arguments对象。
  • 不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

42.Vue的响应式是通过什么实现的。

  • Object.defineProperty

43.一般平时通过什么途径获取前端的知识或者资讯。

44.列举一个自己觉得比较满意的项目,并说明做了哪些功能上的优化。

45.npm版本号一般有哪些写法

46.npm的script里面一般写些什么。

47.webpack的hash的用法

48.git如果某一次提交中有一个文件提交错了,该如何操作。

  • git reset <文件名>

49.SPA首屏比较慢,可以如何优化。

  • 参照31

50.const定义的数组或者对象可以改变吗

  • 数组和对象可以改
  • const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。

51.Objects和Maps的区别

  • 一个对象通常都有自己的原型,所以一个对象总有一个"prototype"键。不过,从 ES5 开始可以使用 map = Object.create(null) 来创建一个没有原型的对象。
  • 一个对象的键只能是字符串或者 Symbols,但一个 Map的键可以是任意值。
  • 可以通过size属性很容易地得到一个Map的键值对个数,而对象的键值对个数只能手动确认。

52.解构的原理

53.从promise谈谈event loop。

54.谈谈浏览器兼容用过哪些。

55.做移动端开发和pc端开发有什么区别。

这个肯定很多区别啊,但是突然这么问,很多一时间就想不到了,参考知乎这个答案有意识的准备一下吧,否则这种开放性的题型,哎....心有千言,却什么都说不出来,仿佛一个智障。

经此一役,我开启了跪读源码的慢慢长征路......