最近换工作,面试了好多公司,遇到了挺多的面试题的,将自己最近的面试题统一一下,做个记录,最近一个月内有空就更新。方便自己学习,以及基础知识的补充。顺便吐槽一下,前端知识跟宇宙一样宽广啊~
16ms 优化:大多数设备的刷新频率是 60 次/秒,(1000/60 = 16.6ms)也就说是浏览器对每一帧画面的渲染工作要在 16ms 内完成,超出这个时间,页面的渲染就会出现卡顿现象,影响用户体验
- JavaScript:JavaScript 实现动画效果,DOM 元素操作等。
- Style(计算样式):确定每个 DOM 元素应该应用什么 CSS 规则。
- Layout(布局):计算每个 DOM 元素在最终屏幕上显示的大小和位置。由于 web 页面的元素布局是相对的,所以其中任意一个元素的位置发生变化,都会联动的引起其他元素发生变化,这个过程叫 reflow。
- Paint(绘制):在多个层上绘制 DOM 元素的的文字、颜色、图像、边框和阴影等。
- Composite(渲染层合并):按照合理的顺序合并图层然后显示到屏幕上。
通过改变元素的 transform 实现移动,伸缩变换而非改变物体的 left,top,width,height 避免 layout,paint
如何开启GPU加速?3D 或透视变换(perspective,transform) CSS 属性;对自己的 opacity 做 CSS 动画或使用一个动画 webkit 变换的元素;CSS过滤器(比如-webkit-filter: grayscale(100%))
资料来源:http://web.jobbole.com/91031/ 侵删
VUE实现双向数据绑定的原理就是利用了 Object.defineProperty() 这个方法,重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。observer、watcher、compiler
BFC 全称为 块格式化上下文。BFC是在css2.1提出的,它决定了元素如何对其内容进行定位,以及与其他元素的关系和如何相互影响。
BFC 特性(功能):1. 使 BFC 内部浮动元素不会到处乱跑;2. 和浮动元素产生边界。
BFC就是一个独立的容器,容器内和容器外的元素不会互相影响。
一个BFC是一个
HTML
盒子并且至少满足下列条件中的任何一个:
float
的值不为none
position
的值不为static
或者relative
display
的值为table-cell
,table-caption
,inline-block
,flex
, 或者inline-flex
中的其中一个overflow
的值不为visible
闭包,就是指能够访问另一个函数作用域的变量的函数。
使用场景:闭包一般的用途在,轮播、幻灯片,setInterval
比如:
// 计数器 var f1 = function () { var count = 0; return function () { return ++count; } }; var fun = f1() fun(); // 1 fun(); // 2
导致内存泄露的场景:循环引用,内部函数引用(闭包) 参考资料
垃圾收集机制的原理其实很简单:找出那些不再继续使用的变量,然后释放其占用的内存
http协议是无状态、无连接的,目前http协议里面版本一般的是1.1的
无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接
无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大
http报文里面主要由四层组成,响应头,请求头和请求体(装载请求数据)
请求头: refferer,accept,cache-control,content-type,cookie,user-agent,pragma,origin等
响应头: allow,content-type,date,status,Access-Control-Allow-Origin,cache-control
常用状态码:
200 请求完成; 202 服务器已接受请求,但尚未处理
301 永久移动; 302 临时重定向; 304 未修改(取缓存);200 OK (from memory/disk cache)
400 客户端请求错误; 401 需要认证; 403 拒绝执行; 404 找不到资源
500 服务器内部错误; 502 错误的网关; 503 服务器不可用(超载或者维护); 504 网关超时
POST、PUT、DELETE等请求永远不会被缓存,GET请求可以被缓存
再说一下http的三次握手和四次挥手,我自己是用打电话这个例子来帮助理解的
三次挥手
1. 首先A打电话给B(也就是客户端想服务器发起请求,想和服务器建立连接)
2. B收到A的电话铃声,接电话,并“喂,是谁啊”(服务器接受了连接,并且想客户端发送询问)
3. A听到了电话那头传过来的语音,就认为电话接通了,“我是某某啊”(客户端收到服务器的确认后,向服务器发送确认,表明连接已经建立了)
A然后就跟B说:“万福金安,三天之内必好运...........”(接下来就是客户端开始发送数据了...)
四次挥手
4. A说完了话(客户端这个时候结束了发送数据,服务端收到客户端结束发送数据的信号)
5. 轮到B回复了A的那一堆话(服务端向客户端发送应该信号,表明服务端即将发送数据)
B开始说话了“三天之内.......” (此时服务端在向客户端发送数据...)
6. B终于说完了,跟A说:“我好了” (此时服务端向客户端发送结束数据传输的信号,表明数据发送已经完成)
7. A听到B终于把话说完了,A说“好,我挂了” ,此时A说完这句话,等了一下,然后才挂断电话(此时,客户端收到服务器发送的数据发送完成信号,就向服务器发送应答信号,表明收到了所有数据,等待2msl后,A关闭连接)
此时B收到了之后,马上就挂断电话
TCP/IP协议是一个协议集合。
TCP/IP 参考模型有四层,分别是应用层,网络层,数据链路层,传输层。
OSI模型:应用层,表示层,会话层,传输层,数据链路层,物理层
1. 创建一个新的对象 var obj = {};
2. 设置新对象的constructor指向构造函数,将新对象的__proto__的对象指向构造函数的prototype对象 obj.__proto__ = class.prototype
3. 使用新对象调用函数,将函数的this指向新的实例对象 class.call(obj)
4. 将初始化完毕的新对象地址,返回到等式左边的变量
输出3 3 3。setTimeout是异步的,它会被放到事件队列中,等待主线程上面的代码执行完后,才执行事件队列中的。所以for循环结束后,i是等于3的,事件队列中的setTimeout开始执行的时候取到的值就是3了,所以输出三次3。
若是要顺序执行0 1 2的话,可这么做:
let的作用就是在每次循环的时候形成封闭的作用域,也就是每次的setTimeout都都绑定有一个特定的值的i
(function() {})()立即执行函数在每次循环的时候,函数都会被立刻执行,每次i的值都会被放在立刻执行的函数作用域里
URL定位资源,用HTTP动词(GET, POST, PUT, DELETE)描述操作
工厂模式、单体模式、构造函数模式、模块模式等等
参考链接: JS几种设计模式
mixins一般是用来混入一些常用的公共方法的,可全局混入或者在组件中混入
以下代码自定义了一个指令v-loadimg,作用就是当图片还没有加载进来的时候,给img标签加随机背景颜色,当图片加载进来的时候,去除背景色。这里只是一个简单的自定义指令的编写
forEach(): 遍历数组,没有返回值
var a = [1,2,3,5] a.forEach((item, index, arr) => { // 元素, 下标, 原数组 console.log(item) }) // 输出: 1, 2, 3, 5
map(): 遍历数组每一个元素,并返回新数组
var a = [1,2,3,4,5] var b = a.map(function (item, index, arr) { // 元素, 下标, 原数组 return item * item }) // 输出[1, 4, 9, 16, 25]
filter(): 过滤掉不符合条件的元素,返回新数组
var a = [1,2,3,4,5] var b = a.filter(function (item, index, arr) { // 元素, 下标, 原数组 return item > 3 }) // 输出[4, 5]
reduce(): 对数组中的所有元素调用指定的回调函数。该回调函数的返回值为累积结果,并且此返回值在下一次调用该回调函数时作为参数提供。
var a = [1,2,3,4,5] var initialVal = 10 // 设定的初始值 可选 var b = a.reduce(function (total, currentValue, currentIndex, arr) { // 初始值、当前元素=》必选 |||| 当前索引、原数组 =》 可选 return total + currentValue }, initialVal) console.log(b) // 输出 25
some(): 遍历数组的每一项,若是遇到符合条件的,返回true,并停止循环;若全部不符合则返回false
var a = [1,2,3,4,5] var b = a.some(function (item, index, arr) { // 当前元素, 下标, 原数组 return item > 3 }) console.log(b) // 输出 true
every(): 遍历数组每一项,若是遇到不符合条件的,则返回false,并停止循环;若全部都符合则返回true
var a = [1,2,3,4,5] var b = a.every(function (item, index, arr) { // 当前元素, 下标, 原数组 console.log(item) return item < 3 }) console.log(b) // 输出 false
通俗理解,就是DOM的操作逻辑和数据处理逻辑分离
EventSource 是 HTML5 中 Server-sent Events 规范的一种技术实现。EventSource 接口用于接收服务器发送的事件。它通过HTTP连接到一个服务器,以text/event-stream 格式接收事件, 不关闭连接。通过 EventSource 服务端可以主动给客户端发现消息,使用的是 HTTP协议,单项通信,只能服务器向浏览器发送; 与 WebSocket 相比轻量,使用简单,支持断线重连
函数调用(指向window) 对象方法(对象) 构造函数(实例化出来的对象) 计时器调用(window) 匿名函数(window)
原型中的this指向调用他的对象不指向本身
- CMD 推崇依赖就近;AMD 推崇依赖前置
- CMD 是延迟执行;AMD 是提前执行
- CMD性能好,因为只有用户需要的时候才执行;AMD用户体验好,因为没有延迟,依赖模块提前执行了
AMD异步,CMD同步
1.浏览器接收URL
2.将URL与缓存进行比对如果请求的页面在缓存中且未过期,则直接进行第8步
3.如果网络地址不是一个 IP 地址,通过DNS解析域名返回一个IP地址
4.浏览器与服务器通过三次握手(SYN,SYN/ACK,ACK)建立TCP 连接
5.浏览器向服务器发送HTTP请求
6.服务器收到请求,从它的文档空间中查找资源并返回HTTP响应
7.浏览器接受 HTTP 响应,检查 HTTP header 里的状态码,并做出不同的处理方式
8.如果是可以缓存的,这个响应则会被存储起来
9.解码 10.渲染
标签选择器(div p),类选择器(class="header"),ID选择器(id="header"),全局选择器(*),伪类选择器(:after, :before),继承选择器(div p),后代选择器(A>B),任意选择器(A,B)
重排:若渲染树的一部分更新,且尺寸变化,就会发生重排,可以理解为渲染树需要重新计算;(比如width, height, display:none / block, left, top...)
重绘:一个元素外观的改变所触发的浏览器行为,例如改变visibility、outline、font-size、color、background等属性
重排必定会引发重绘,但重绘不一定会引发重排
transform会导致重排么?https://blog.csdn.net/weixin_33922670/article/details/89108346
参考: https://www.cnblogs.com/focusxxxxy/p/6390536.html
DNS Prefetch
精灵图,减少http连接数,减少dom的操作,使用gpu加速
CSRF:是一种伪造跨站请求的攻击方式. 例如利用你在 A 站 (攻击目标) 的 cookie / 权限等, 在 B 站 (恶意/钓鱼网站) 拼装 A 站的请求.
CSRF预防方法:在 HTTP 头中自定义属性并验证;cookie中加入hash随机数;通过检查来过滤简单的 CSRF 攻击, 主要检查一下两个 header:Origin Header, Referer Header (origin只用于Post请求,而Referer则用于所有类型的请求;)
XSS:跨站脚本 (Cross-Site Scripting, XSS) 是一种代码注入方式
最简单的深拷贝:
var test = {a: 1, b: 2, c: [1, 2, 3]} var copyTest = JSON.parse( JSON.stringify(test) )
使用递归进行深拷贝:
function copy(obj) { var arr = Array.isArray(obj) ? [] : {} if (typeof obj === 'object') { for (key in obj) { if (obj.hasOwnProperty(key)) { // 如果子元素是对象,递归操作 if (obj[key] && typeof obj[key] === 'object') { arr[key] = deep(obj[key]) } else { arr[key] = obj[key] } } } } return arr } // 使用jQuery var testObj = { name: 'lin', hobbit: ['swimming', 'reading'] } $.extend(true, {}, testObj)
感谢网上的一些大佬文章的解决方案