2016-10-19-小米前端面试
本文最后更新于:2023年3月30日 下午
一面
1. 说一下CSS的盒模型?
盒模型:文档中的每个元素被描绘为矩形盒子,渲染引擎的目的就是判定大小,属性——比如它的颜色、背景、边框方面——及这些盒子的位置。
在CSS中,这些矩形盒子用标准盒模型来描述。这个模型描述了一个元素所占用的空间。每一个盒子有四条边界:外边距边界margin edge,边框边界border edge,内边距边界padding edge和内容边界content edge。
内容区域是真正包含元素内容的区域,位于内容边界的内部,它的大小为内容宽度或content-box宽及内容高度或content-box高。如果box-sizing为默认值,width、min-width、max-width、height、min-height和max-height控制内容大小。
内边距区域padding area用内容可能的边框之间的空白区域扩展内容区域。通常有背景——颜色或图片(不透明图片盖住背景颜色)。
边框区域扩展了内边距区域。它位于边框边界内部,大小为border-box宽和border-box高。
外边距区域margin area用空白区域扩展边框区域,以分开相邻的元素。它的大小为margin-box的高宽。
在外边距合并的情况下,由于盒之间共享外边距,外边距不容易弄清楚。
对于非替换的行内元素来说,尽管内容周围存在内边距与边框,但其占用空间(行高)由line-height属性决定。
2. 常用的跨域方法:
.图像Ping:使用标签,因为网页可以从任何网页中加载图片,而不用担心跨域。请求数据通过字符串形式发送,而响应可以是任何内容。这种方法,1)只能发送get请求。2)浏览器无法获取响应数据。3)只适用于浏览器与服务器之间的单向通信
.JSONP:通过动态<script>
元素使用,使用时为src指定一个跨域url。有两部分:1)回调函数:响应到来时在页面中使用;2)数据:传入回调函数中的JSON数据
.后台代理方法:将后台作为代理,每次对其它域的请求转交给本域的后台,本域的后台通过模拟http请求去访问其它域,再将返回的结果返回给前台
.设置document.domain:只适用于主域相同子域不同
.使用window.name:+iframe。应用页面创建iframe,src指向数据页面;数据页面把数据附加到window.name上;应用界面监听iframe的onload事件,在此事件中设置这个iframe的src指向本地域的代理文件;获取数据后销毁iframe
.使用html5新方法:window.postMessage(message, targetOrigin)
3. 说一下js中的事件
事件模型在不断发展,早期的事件模型称为DOM0级别。DOM0事件模型,所有的浏览器都支持。直接在dom对象上注册事件名称,就是DOM0写法,比如:
1 |
|
意思就是注册一个onclick事件。当然,它和这种写法是一个意思:
1 |
|
这没什么,只不过是两种访问js对象属性的方法,[]的形式主要是为了解决属性名不是合法的标识符,比如:object.123
肯定报错,但是object['123']
就避免了这个问题,与此同时,[]的写法,也把js写活了,用字符串表示属性名称,可以在运行时动态绑定事件。
言归正传,事件被触发时,会默认传入一个参数e,表示事件对象,通过e,我们可以获取很多有用的信息,比如点击的坐标、具体触发该事件的dom元素等等。
基于DOM0的事件,对于同一个dom节点而言,只能注册一个,后边注册的同种事件会覆盖之前注册的。例如:
1 |
|
结果会输出ok1。
接下来再说说this。事件触发时,this就是指该事件在哪个dom对象上触发。例如:
1 |
|
结果输出test。因为事件就是在id为test的dom节点上注册的,事件触发时,this当然代表这个dom节点,可以理解为事件是被这个dom节点调用的。
所以,想解除事件就相当简单了,只需要再注册一次事件,把值设成null,例如:
1 |
|
原理就是最后注册的事件要覆盖之前的,最后一次注册事件设置成null,也就解除了事件绑定。
事情还没结束,DOM0事件模型还涉及到直接写在html中的事件。例如:
1 |
|
通过这种方式注册的事件,同样遵循覆盖原则,同样只能注册一个,最后一个生效。
区别就是,这样注册的事件,相当于动态调用函数(有点eval的意思),因此不会传入event对象,同时,this指向的是window,不再是触发事件的dom对象。
DOM2事件模型:
DOM2事件模型相对于DOM0:
·DOM2支持同一dom元素注册多个同种事件。
·DOM2新增了捕获和冒泡的概念。
DOM2事件通过addEventListener
和removeEventListener
管理,当然,这是标准。
但IE8及其以下版本浏览器,自娱自乐,搞出了对应的attachEvent
和detachEvent
,由于我才疏学浅,本文不做讨论。
addEventListener
当然就是注册事件,她有三个参数,分别为:”事件名称”, “事件回调”, “捕获/冒泡”。举个例子:
1 |
|
事件名称就不用多说了,相比DOM0,去掉了前边的on而已。
事件回调也很好理解,事件触发了总得通知你吧!回调时和DOM0一样,也会默认传入一个event参数,同时this是指触发该事件的dom节点。
最后一个参数是布尔型,true代表捕获事件,false代表冒泡事件。其实很好理解(默認 false),先来个示意图:
意思就是说,某个元素触发了某个事件,最先得到通知的是window,然后是document,依次而入,直到真正触发事件的那个元素(目标元素)为止,这个过程就是捕获。接下来,事件会从目标元素开始起泡,再依次而出,直到window对象为止,这个过程就是冒泡。
为什么要这样设计呢?这貌似是由于深厚的历史渊源,我也不怎么了解,就不乱说了。
由此可以看出,捕获事件要比冒泡事件先触发。
假设有这样的html结构:
1 |
|
然后我们在外层div上注册两个click事件,分别是捕获事件和冒泡事件,代码如下:
1 |
|
最后,点击内层的div,先弹出ok1,后弹出ok。结合上边的原理图,外层div相当于图中的body,内层div相当于图中最下边的div,证明了捕获事件先执行,然后执行冒泡事件。
为什么要强调点击内层的div呢?因为真正触发事件的dom元素,必须是内层的,外层dom元素才有机会模拟捕获事件和冒泡事件,从原理图上就看出了。
如果在真正触发事件的dom元素上注册捕获事件和冒泡事件呢?
html结构同上,js代码如下:
1 |
|
当然还是点击内层div,结果是先弹出ok,再弹出ok1。理论上应该先触发捕获事件,也就是先弹出ok1,但是这里比较特殊,因为我们是在真正触发事件的dom元素上注册的事件,相当于在图中的div上注册,由图可以看出真正触发事件的dom元素,是捕获事件的终点,是冒泡事件的起点,所以这里就不区分事件了,哪个先注册,就先执行哪个。本例中,冒泡事件先注册,所以先执行。
这个道理适用于多个同种事件,比如说一下子注册了3个冒泡事件,那么执行顺序就按照注册的顺序来,先注册先执行。例如:
1 |
|
结果当然是依次弹出ok、ok1、ok2。
为了进一步理解事件模型,还有一种场景,假如说外层div和内层div同时注册了捕获事件,那么点击内层div时,外层div的事件一定是先触发的,代码如下:
1 |
|
结果是先弹出ok1。
假如外层div和内层div都是注册的冒泡事件,点击内层div时,一定是内层div事件先执行,原理相同。
细心的读者会发现,对于div嵌套的情况,如果点击内层的div,外层的div也会触发事件,这貌似会有问题!
点击的明明是内层div,但是外层div的事件也触发了,这的确是个问题。
其实,事件触发时,会默认传入一个event对象,前边提过了,这个event对象上有一个方法:stopPropagation,通过此方法,可以阻止冒泡,这样外层div就接收不到事件了。代码如下:
1 |
|
终于要说说怎么解除事件了。解除事件语法:btn.removeEventListener('事件名称', '事件回调', '捕获/冒泡')
;
这和绑定事件的参数一样,详细说明下:
· 事件名称,就是说解除哪个事件呗。
· 事件回调,是一个函数,这个函数必须和注册事件的函数是同一个。
· 事件类型,布尔值,这个必须和注册事件时的类型一致。
也就是说,名称、回调、类型,三者共同决定解除哪个事件,缺一不可。举个例子:
1 |
|
要想注册过的事件能够被解除,必须将回调函数保存起来,否则无法解除。
4. 说一下cookie
和localeStorage
,sessionStorage
。
cookie:
cookie是网站为了标示用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。
cookie数据始终在同源的http请求中携带(即使不需要),记会在浏览器和服务器间来回传递。
sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
存储大小:
cookie数据大小不能超过4k。
sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
有期时间:
localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;
sessionStorage 数据在当前浏览器窗口关闭后自动删除。
cookie 设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
作用域不同:
sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;
localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。
Web Storage 支持事件通知机制,可以将数据更新的通知发送给监听者。
Web Storage 的 api 接口使用更方便。
sessionStorage 和 localStorage 是HTML5 Web Storage API 提供的,这两种方式都允许开发者使用js设置的键值对进行操作,在在重新加载不同的页面的时候读出它们。这一点与cookie类似。可以方便的在web请求之间保存数据。有了本地数据,就可以避免数据在浏览器和服务器间不必要地来回传递。
sessionStorage、localStorage、cookie都是在浏览器端存储的数据, 其中sessionStorage的概念很特别,引入了一个“浏览器窗口”的概念。
sessionStorage是在同源的同窗口(或tab)中,始终存在的数据。也就是说只要这个浏览器窗口没有关闭,即使刷新页面或进入同源另一页面,数据仍然存在。关闭窗口后,sessionStorage即被销毁。同时“独立”打开的不同窗口,即使是同一页面,sessionStorage对象也是不同的。
Web Storage 数据完全存储在客户端, 不需要通过浏览器的请求将数据传给服务器, 因此比cookies能够存储更多的数据,大概5M左右
Web Storage带来的好处:
使用 local storage和session storage主要通过在js中操作这两个对象来实现,分别为window.localStorage和window.sessionStorage. 这两个对象均是Storage类的两个实例,自然也具有Storage类的属性和方法。
减少网络流量:一旦数据保存在本地后,就可以避免再向服务器请求数据,因此减少不必要的数据请求,减少数据在浏览器和服务器间不必要地来回传递。
快速显示数据:性能好,从本地读数据比通过网络从服务器获得数据快得多,本地数据可以即时获得。再加上网页本身也可以有缓存,因此整个页面和数据都在本地的话,可以立即显示。
临时存储:很多时候数据只需要在用户浏览一组页面期间使用,关闭窗口后数据就可以丢弃了,这种情况使用sessionStorage非常方便。
5. get和post的区别
答出常見的區別后,
1). 可以試著說出post的不一樣,會進行握手請求(options);
2). 本質上是get和post是沒有區別的,詳見互聯網的答案;
6. js继承
7. 写一个把数组打乱顺序的函数
1 |
|
8. js实现url解析
1 |
|
1 |
|
9. 讲一下css的动画
主要是: @keyframes
和 animation
keyframes有: 百分數、from / to
animation主要是調用keyframes動畫:
属性 | 描述 | CSS |
---|---|---|
@keyframes |
规定动画。 | 3 |
animation |
所有动画属性的简写属性,除了 animation-play-state 属性。 | 3 |
animation-name |
规定 @keyframes 动画的名称。 | 3 |
animation-duration |
规定动画完成一个周期所花费的秒或毫秒。默认是 0。 | 3 |
animation-timing-function |
规定动画的速度曲线。默认是 ease 。 |
3 |
animation-delay |
规定动画何时开始。默认是 0。 | 3 |
animation-iteration-count |
规定动画被播放的次数。默认是 1 | 3 |
animation-direction |
规定动画是否在下一周期逆向地播放。默认是 “normal”。 | 3 |
animation-play-state |
规定动画是否正在运行或暂停。默认是 running 。 |
3 |
animation-fill-mode |
规定对象动画时间之外的状态。 | 3 |
10. 猜一下,如果要绑定动画的话,在哪里绑定?怎么绑定?
綁定到選擇器中
二面
1. 说一下margin吧。如果两个div,上面的div一个margin,下面的div一个margin,那么它们之间的距离会是谁的margin?
這道題說的是塌陷問題:誰的margin大就是誰的
2. 如果是父级margin和子div的margin呢?父元素到上面的margin是多少?子元素到上面元素的margin是多少?
父级的实际margin-top
实际自己是多少就是多少,子级是多少就是多少,但是父级盒子会受到子级影响,谁最大实际效果就是多少,有点类似塌陷;
3. 还是上面那个,如果子div是浮动的呢?
这个是IE6的双边距bug,解决办法是设置为:display:inline
4. 如果是行内元素呢?如果字体font-size是10px,行高line-height是2px,显示多高?
显示高为: 2px,超过的文字会重叠在一起
5. nginx匹配规则:
没有做过不会,网上找的答案
= 表示精确匹配
~ 表示区分大小写的正则匹配
^~ 表示以某个常规字符串开头的url即可;
~* 表示不区分大小寫的正则匹配
!(*!)表示不区分大小写不匹配的正则
/ 通配符,任何请求都能匹配到这个location,如果有任何其他location可以匹配,则会覆盖该location
匹配顺序:
1)先匹配普通url,在匹配正则
2)“普通 location ”的匹配规则是“最大前缀”,因此“普通 location ”的确与 location 编辑顺序无关;
3)location的执行逻辑基本上跟顺序没有关系;但是针对正则匹配的方式,匹配上第一个url,就不在继续匹配后面的url;
这种情况,如果匹配上普通localtion,没有正则匹配,则使用普通匹配;如果既有普通location的最大前缀匹配,也有正则匹配,则正则匹配覆盖最大前缀匹配。
4)匹配完“普通 location ”后,有的时候需要继续匹配“正则 location ”,有的时候则不需要继续匹配“正则 location ”。
两种情况下,不需要继续匹配正则 location :(1) 当普通 location 前面指定了“ ^~ ”,特别告诉 Nginx 本条普通 location 一旦匹配上,则不需要继续正则匹配;(2) 当普通location 恰好严格匹配上,不是最大前缀匹配,则不再继续匹配正则。
6. 说一下em和rem的区别:
em 是指相对于父级设置的大小进行百分比设置,通常会设置body为62.%(10 / 16)
rem 是指相对于文档body的大小进行设置,不存在相對於父級的複雜的换算
7. ajax原生
1 |
|
get请求:
1 |
|
post请求
1 |
|
8. 实现一个小游戏,一个页面,上半部分很多方块,然后有一个小球,可以手指拖动控制位置和弹射方向,碰到方块后方块会消失。怎么实现?
詳見: 重力+拖拽+碰撞的演示
9. 了解jQuery吗?(我说看过部分的源码),然后她问选择器了解吗?(我说这个没看,知道是用sizzle,然后说了下我的一些理解,比如判断jQuery对象啦,取字符串正则匹配这样)
三面:(其他的是硬件的不貼了)
1.jpg和png的区别?
我不懂,就说是压缩和无压缩吗?但是当然不是。。
然后说起来png也有png-8,png-24,png-32这样。然后问我知道是什么意思吗?不懂。面试官解释是指存储位数,png-32是存储32=8*4位,255,255,255,255,分别是rgba。而png-24没有alpha值,那么png-8是怎么存储的呢?怎么能把32位压缩成8位呢?我想了半天,感觉不能把8位压缩成2位,如果8个像素点一组的话也太失真了感觉。。。然后面试官让我说一下思路,我就直说想不出来,想不到怎么把8位信息用2位来表示出来,于是他给了提示是索引……然后我就猜是有一个数组保存一些颜色的值,然后png-8每个像素点存储的是索引值……好厉害。然后问到索引里保存的是什么?是频率最高的颜色吗?我说应该是一个范围吧……但是这样会不会失真太严重,然后他说这都还是个坑,还在研究中。。。
原文來自互聯網,答案自己有貼上去的~~