酷狗一面
1. 如何实现三栏布局(左右两边固定宽度,中间自适应)?
- 使用flex布局: 父元素设置
display: flex
,左右两边设置固定宽度,中间设置flex-grow: 1
;- 使用浮动布局:左右两边设置固定宽度,而且分别设置
float:left和right
,这个方法有一个需要注意的是在HTML中,中间栏需要和右边栏进行对调;- 使用绝对定位布局:左右两边设置固定宽度和
position:absolute
,而且分别设置left: 0
和right: 0
,中间栏只要设置左右margin为左右栏的宽度就可以了(需要注意的是左右两边需要设置top: 0
,不然右边会被顶下来)
补充
其实还有表格布局,网格布局和圣杯布局,详细请看三栏布局的5种解决方案及优缺点
2. 如何实现弹窗水平垂直居中?
<div class="dialog">
<div class="dialog-content"></div>
</div>
position
元素已知宽度:
.dialog{
position: relative;
width: 500px;
height: 500px;
background: goldenrod
}
.dialog-content{
width: 200px;
height: 200px;
background: rebeccapurple;
position: absolute;
top: 50%;
left: 50%;
margin:-100px 0 0 -100px;
}
transform
元素未知宽度
.dialog{
position: relative;
width: 500px;
height: 500px;
background: goldenrod
}
.dialog-content{
width: 200px;
height: 200px;
background: rebeccapurple;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
flex
布局
.dialog {
width: 500px;
height: 500px;
background: goldenrod;
display: flex;
justify-content: center;
align-items: center;
}
.dialog-content {
width: 200px;
height: 200px;
background: rebeccapurple;
}
3. ==
和 ===
的区别
===
为恒等符:当等号两边的值为相同类型的时候,直接比较等号两边的值,值相同则返回true,若等号两边的值类型不同时直接返回false。
==
为等值符: 当等号两边的值为相同类型时比较值是否相同,类型不同时会发生类型的自动转换,转换为相同的类型后再作比较。
a、如果一个是null、一个是undefined,那么[相等]。
b、如果一个是字符串,一个是数值,把字符串转换成数值再进行比较。
c、如果任一值是 true,把它转换成 1 再比较;如果任一值是 false,把它转换成 0 再比较。
d、如果一个是对象,另一个是数值或字符串,把对象转换成基础类型的值再比较。对象转换成基础类型,利用它的toString或者valueOf方法。 js核心内置类,会尝试valueOf先于toString;例外的是Date,Date利用的是toString转换。非js核心的对象,令说(比较麻 烦,我也不大懂)
e、任何其他组合,都[不相等]。
4. 30 ==
'30' 的过程是怎样的?
- 30为数值类型,而'30'未字符串类型,因此等号两边的数据类型不相等,需要进行转换类型;
- 由于一个是数值,另一个字符串,所以需要将字符串转换成数值再进行比较,即
'30' => 30
;- 这时等号两边同样为数值型数据,即
30 == 30
,所以返回true
5. 以下代码输出的是什么?为什么呢?
for (var i=0; i<5; i++) {
setTimeout( function timer() {
console.log(i);
}, 0 );
}
回答: 直接输出 5 5 5 5 5
首先这里涉及到setTimeout
的执行顺序,页面中所有由setTimeout
定义的操作,都将放在同一个队列中(这里涉及到两种,微任务队列和宏任务队列,刚好下面问Promise的时候就问到了)依次执行。这个队列执行的时间,需要等待到函数调用栈清空之后才开始执行。即所有可执行代码执行完毕之后,才会开始执行由
setTimeout
定义的操作。而这些操作进入队列的顺序,则由设定的延迟时间来决定。根据
setTimeout
定义的操作在函数调用栈清空之后才会执行的特点,for循环里定义了5个setTimeout
操作,这些setTimeout
操作是在循环执行完成后才开始执行,这个时候i = 5
,因为每个setTimeout
操作的延迟时间一样,所以按顺序输出5 5 5 5 5
6. 你有使用过闭包吗?
7. 模块化的异步加载怎样做?
8. window.onload
执行时间?
9.图片加载完的时候会执行吗?
10. 了解JS继承吗?
11. 利用原型链的继承有什么缺点吗?
12. 知道如何修改this的指向吗?
修改this指向的办法有三种:apply
、call
和bind
apply
、call
:通过传入需要指向的对象,从而改变this
的指向,指向传入的第一个参数;bind
:它会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。
window.color = 'red';
var o = { color:'blue' };
function sayColor(){
console.log(this.color);
}
var globalSaycolor = sayColor;
var objectSaycolor = sayColor.bind(o);
globalSaycolor(); // red
objectSaycolor(); // blue
补充
其实还有一种:new关键字改变this指向
因为在new
的过程中,其中有一个步骤为将构造函数内部的this
指向实例对象,所以通过new关键字
也可以改变this
的指向。
13. apply
和call
的区别?
相同点:可以用来代替另一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由thisObj指定的新对象。不同点:实际上,
apply
和call
的功能是一样的,只是传入的参数列表形式不同。apply
:最多只能有两个参数——新this
对象和一个数组argArray
。如果给该方法传递多个参数,则把参数都写进这个数组里面,当然,即使只有一个参数,也要写进数组里。如果argArray
不是一个有效的数组或arguments
对象,那么将导致一个TypeError
。如果没有提供argArray
和thisObj
任何一个参数,那么Global对象将被用作thisObj
,并且无法被传递任何参数。
call
:它可以接受多个参数,第一个参数与apply
一样,后面则是一串参数列表。这个方法主要用在js对象各方法相互调用的时候,使当前this实例指针保持一致,或者在特殊情况下需要改变this指针。如果没有提供thisObj
参数,那么 Global 对象被用作thisObj
。
14. 有一个按钮是异步生成的,怎样对它进行事件绑定?
由于按钮是异步生成的,所以我选择将事件绑定在按钮生成的父元素上,通过事件委托的机制,利用事件冒泡,把事件绑定在父元素上,可以通过判断event.target
按钮是否已经生成,从而实现相应的事件。科普补充:
事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。也就是说,事件会从最内层的元素开始发生,一直向上传播,直到document
对象;
事件捕获则跟事件冒泡相反,事件会从document
对象开始发生,直到最具体的元素;
15. 跨域有处理过吗?
我处理过的跨域有两种情况:
- 一种是在页面中嵌入了一个iframe,因此父子iframe间产生了跨域,要解决这个问题,只需要把
document.domain
设置成相同的值就可以在两个页面里进行相应的操作了;- 另外一种情况是用Vue开发涉及到的跨域问题,这个问题只需要修改config文件夹下的index.js中的dev:{}部分中修改proxyTable参数即可,相当于对跨域的url进行了代理,从而可以顺利访问。
另外说了一下自己比较熟悉的一种跨域解决方案:JSONP
JSONP解决跨域问题的本质其实就是<script>
标签可以请求不同域名下的资源,即<script>
请求不受浏览器同源策略影响。
面试官听到JSONP立刻提出了一个问题:JSONP是否可以支持POST
方法?为什么?
JSONP只支持GET
的请求方法,上面也提到了JSONP原理其实就是利用<script>
标签发送了一个URL
给服务器,其实与ajax XMLHttpRequest
协议无关了,相当于输入了一个url
而已,所以必然只能为GET
请求方法。
16. 既然提到POST
和GET
,说说两者的区别?
- 大小:
GET
提交的数据最大为2k(原则上url长度无限制,可是浏览器通常限制url长度在2k左右);POST
理论上没有限制大小(实际上IIS4中最大量为80KB,IIS5中为100KB)。- 发送方式:
GET
请求数据放在url上,即HTTP协议头中,其格式为:url?key=value&key2=value
;POST
把数据放在HTTP的包体中(Request Body)。- 安全性:
GET
请求可被缓存,请求保存在浏览器历史记录中;POST
则不能被缓存。与POST
相比,GET
的安全性较差,因为发送的数据是URL的一部分。- 发送TCP包:对
GET
请求只产生一个TCP包,浏览器会把http header
和data
一并发送出去,服务器响应200
(返回数据);对于POST
请求产生两个TCP数据包,浏览器先发送http header
,服务器确认权限正确响应100
(continue)返回浏览器,浏览器收到100
确认继续请求,再次发送data
,服务器响应200
(返回数据)。
17. 听到你提到浏览器,你了解浏览器缓存的方式吗?
浏览器缓存类型有两种,强缓存和协商缓存
- 强缓存:不会向服务器发送请求,直接从缓存中读取资源(
Expires --> HTTP 1.0
或cache-control --> HTTP 1.1
);- 协商缓存:向服务器发送请求,服务器会根据这个请求的
If-None-Match
和If-Modified-Since
来判断是否命中协商缓存,如果命中,则返回304状态码并带上新的response header
通知浏览器从缓存中读取资源;具体流程参考下图:
补充
共同点: 都是从客户端缓存中读取资源
不同点: 强缓存不会发送请求;协商缓存会发请求。
18. 看你有用过Promise,知道Promise有几种状态?
Promise 有三个状态Pending
、Fulfilled
和Rejected
,只能从Pending
转换为Fulfilled
,和Pending
转换为Rejected
,状态一旦改变就不能再次变化。
19. 你知道pending
状态可以停止吗?
20. 那XMLHttpRequest 的pending
状态可以停止吗?
21. 知道Promise和setTimeout的执行顺序吗?
如果Promise
和setTimeout
同时存在的话,一般是先执行Promise
之后再执行setTimeout
。因为这里涉及到微任务队列(Microtasks)和宏任务队列(Macrotasks)。microtasks queue
中的内容经常是为了需要直接在当前脚本执行完后立即发生的事,所以当同步执行完之后就调用队列中的内容,然后把异步队列中的setTimeout
放入执行栈中执行。
科普补充
理解 JavaScript 中的 macrotask 和 microtask
Tasks, microtasks, queues and schedules
22. vue中生命周期中的钩子函数用过哪些?
- 首先可以在
beforecreate
中添加一个loading
,然后在created
中结束这个loading
,还做一些初始化,实现函数自执行;- 可以在
mounted
中向后台请求数据,进行页面的渲染;- 可以
update
中对data中的数据进行检测,实现对页面的修改。
23. 为什么在created函数向后台获取数据中?
如果把数据获取放在created
中,如果数据量很大,会出现页面加载缓慢的结果……
这两个问题回答的不是非常的好,希望有人可以帮忙解答一下吗?
24. 对Vue的数据双向绑定有了解吗?
经典问题,具体参考剖析Vue原理&实现双向绑定MVVM
25. 了解重绘和回流吗?页面的加载顺序?
重绘:当元素的一部分属性发生变化,如外观背景色不会引起布局变化而需要重新渲染的过程;
回流: 当render树中的一部分或者全部因为大小边距等问题发生改变而需要重建的过程;
回流一定会发生重绘,重绘不一定引发回流。
页面加载的顺序:
- 浏览器解析HTML文件构建DOM树;
- 解析CSS文件构建Style Rules;
- 两者合并生成Render Tree;
- Layout 根据Render Tree计算每个节点的信息;
- Painting 根据计算好的信息绘制整个页面;
P.S 当文档加载过程中遇到JS文件,HTML文档会挂起渲染过程,不仅要等到文档中JS文件加载完毕还要等待解析执行完毕,才会继续HTML的渲染过程
26. 如何减少回流、重绘?怎样控制只有一部分回流?
一. CSS中避免回流
- 尽可能在DOM树的最末端改变class
- 避免设置多层内联样式
- 动画效果应用到position属性为absolute或fixed的元素上
- 牺牲平滑度换取速度
- 避免使用table布局
- 避免使用CSS的JavaScript表达式
二. JS操作避免回流
- 避免逐项更改样式。最好一次性更改style属性,或者将样式列表定义为class并一次性更改class属性。
- 避免循环操作DOM。创建一个documentFragment或div,在它上面应用所有DOM操作,最后再把它添加到window.document。
- 也可以在一个display:none的元素上进行操作,最终把它显示出来。因为display:none上的DOM操作不会引发回流和重绘。
- 避免循环读取offsetLeft等属性。在循环之前把它们存起来。
- 绝对定位具有复杂动画的元素。绝对定位使它脱离文档刘,否则会引起父元素及后续元素大量的回流。
27. 了解什么算法?快排?
28. 还了解什么排序算法?
29. 了解二叉查找树吗?
30. 有了解什么后端语言吗?知道面向对象的特性吗?
31. 知道数据库连接池吗?
32. 未来前端的规划?
酷狗二面
在面完第一面之后,本来以为终于结束了,没想到迎来的是第二技术面,后面面试官介绍说其实本来是应该两个人同时面我的,因为有一个面试官没空,所以就错开了,就有了"二面"了,其实本质上还是一面而已。
1. 自我介绍
2. 问了一下笔试的时候不应该错的题
3. 理解的HTTP状态码有哪些?
1XX系列:指定客户端应相应的某些动作,代表请求已被接受,需要继续处理;
2XX系列:代表请求已成功被服务器接收、理解、并接受;
3XX系列:代表需要客户端采取进一步的操作才能完成请求,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的 Location 域中指明;301:被请求的资源已永久移动到新位置;
302:请求的资源临时从不同的URI响应请求,但请求者应继续使用原有位置来进行以后的请求;
304:资源找到但是不符合请求条件,不会返回任何主体(用于协商缓存,表示浏览器缓存资源未改变,仍然可用);4XX系列:表示请求错误。代表了客户端看起来可能发生了错误,妨碍了服务器的处理。
5xx系列:代表了服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理。
4. 正则的题目,对比/^[a-z0-9][a-z]+$/
和 /^[a-z0-9][a-z]*$/
的区别?
两者的区别主要是最后的*
和+
,+
出现一次或多次(至少出现一次),等价于{1, }
*
出现零次或多次(任意次),等价于{0, }
最后再借助正则可视化对比就很明显了
5. display:none
和 visibility:hidden
的区别?
visibility:hidden
:所占据的空间位置仍然存在,仅为视觉上的完全透明;visibility:hidden
变化不会触发reflow。display:none
: 不为被隐藏的对象保留其物理空间。display:none
变化时将触发reflow;
科普补充
CSS魔法堂:display:none与visibility:hidden的恩怨情仇
6. CSS选择器的理解,你知道多少选择器?
7. CSS3布局,移动端有用过rem吗?布局的话一般怎样布局?
8. Flex布局和传统的其他布局有什么优点?
9. Flex的居中方式有哪些?其他方式有哪些?
可参考一面的第一和第二个问题。
10. display设置inline-block的话,多个之间有间隔应该怎样处理?
li{
display: inline-block;
background: red;
width: 300px;
height: 100px;
}
<div>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>
浏览器会把inline元素间的空白字符(空格、换行、Tab等)渲染成一个空格。而为了美观。我们通常是一个<li>
放在一行,这导致<li>
换行后产生换行字符,它变成一个空格,占用了一个字符的宽度。
解决:
方法一:为<li>
设置float: left
。不足:有些容器是不能设置浮动,如左右切换的焦点图等。
方法二:将所有<li>
写在同一行。不足:代码不美观。
方法三:将<ul>
内的字符尺寸直接设为0,即font-size: 0
。不足:<ul>
中的其他字符尺寸也被设为0,需要额外重新设定其他字符尺寸,且在Safari浏览器依然会出现空白间隔。
方法四:消除<ul>
的字符间隔letter-spacing: -8px
,而这也设置了<li>
内的字符间隔,因此需要将<li>
内的字符间隔设为默认letter-spacing: normal
。
11. 更熟悉那方面的技术栈?
12. 对自己项目是怎样设计和选型的?
13. 有用到vuex吗?
14. 组件之间的通讯怎样做到?
有多种方法解决
- 使用一个空的 Vue 实例作为中央事件总线
- 使用Vuex
- 使用localStorage和SessionStorage
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。