前端面试常见问题总结
问题陈列
JS相关问题
JavaScript原型,原型链 ? 有什么特点?
每个对象都会在其内部初始化一个属性,就是prototype(原型)。
当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,于是就这样一直找下去,也就是我们平时所说的原型链的概念。This对象的理解
this总是指向函数的直接调用者;
如果有new关键字,this指向new出来的那个对象;
this的指向问题:
1.作为对象的属性被调用,this指向该对象
2.作为普通函数得调用,this总是指向全局对象(通常为window),严格模式下this指向undefined
3.作为构造器调用,通常情况下this指向被构造函数返回的实例,例外如果构造函数显式的返回一个Object类型的对象,name结构也是只会得到这个对象
4.call和apply调用
动态改变this指向,使用一个指定的this值和单独给出的一个或多个参数来调用一个函数
允许为不同的对象分配和调用属于一个对象的函数/方法
call()方法:指定的this + 多个参数
apply()方法:指定的this + 一个包含多个参数的数组
5.箭头函数,箭头函数不会创建自己的this,它会从自己的作用域的上一层继承this
null,undefined 的区别?
null 表示一个对象是“没有值”的值,也就是值为“空”;undefined 表示一个变量声明了没有初始化(赋值);
undefined不是一个有效的JSON,而null是;
undefined的类型(typeof)是undefined;null的类型(typeof)是object;JS 深浅拷贝
深拷贝和浅拷贝是只针对引用数据类型,例如:Object和Array;
浅拷贝只复制指向某个对象的指针而不复制对象本身,新旧对象还是共享同一块内存;
深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象;
深拷贝方法:
1.JSON.parse(JSON.stringify(obj))
原理: 用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。
2.递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝
1 | // 经典问题 |
闭包处理的还是作用域的问题,解决该问题的方法还可以是利用ES6语法,var声明改成let声明
浏览器相关问题
结构层:由 HTML 或 XHTML之类的标记语言负责创建。标签,也就是那些出现在尖括号里的单词,对网页内容的语义含义做出了描述,但这些标签不包含任何关于如何显示有关内容的信息。例如,P标签表达了这样一种语义:“这是一个文本段。”
表示层:由 CSS 负责创建。 CSS对“如何显示有关内容”的问题做出了回答。
行为层:负责回答“内容应该如何对事件做出反应”这一问题。这是 Javascript 语言和 DOM主宰的领域。
1.服务器角度
采取CDN加速,开启gzip压缩,允许使用强缓存或协商缓存,增加服务器带宽
2.客户端角度
合理组织CSS、JavaScript代码位置,减少DOM操作、添加事件委托,部分操作可设置防抖和节流,对于可预见的操作采取preload或prerender的预加载,对于图片可以懒加载,合并CSS图片(精灵图/雪碧图),减少使用iframe,资源优化打包角度
3.资源优化打包角度
使用打包工具将Js文件、CSS文件和静态文件进行恰当打包处理。
跨域问题来自于浏览器的同源策略,即当协议、域名、端口号任意一个不同时,都会引发跨域问题。
解决方法:jsonp、CORS
宏任务是由宿主发起的(Node、浏览器),而微任务由JavaScript自身发起(JS引擎)。
| 宏任务(macrotask) | 微任务(microtask) | |
|---|---|---|
| 发起者 | Node、浏览器 | JS引擎 |
| 具体事件 | 1. script (可以理解为外层同步代码) 2. setTimeout/setInterval 3. UI rendering/UI事件 4. postMessage,MessageChannel 5. setImmediate,I/O(Node.js) |
1. Promise 2. MutaionObserver 3. Object.observe(已废弃; Proxy 对象替代)4. process.nextTick(Node.js) |
| 运行顺序 | 后运行 | 先运行 |
| 触发新一轮Tick | 会 | 不会 |
其中比较注意的是promise的内部既包含宏任务也包含微任务,promise内部执行为宏任务,then执行为微任务
HTML相关问题
1 | 1.语义标签 |
webworker认识
Web Worker的作用就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。
Worker线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。
src是指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置;在请求src资源时会将其指向的资源下载并应用到文档内,例如js脚本,img图片和frame等元素。
CSS相关问题
border-radius:实现倒角、圆角
box-shadow:阴影
text-shadow:字体阴影
gradient:渐变
transform:rotate scale skew translate 旋转 缩放 定位 倾斜
animation:动画
等等
1.id选择器 #id
2.类选择器 .class
3.标签选择器 div
4.相邻选择器 div+p
5.子选择器 div>p
6.后代选择器 div p
7.属性选择器 div[class=”main”]
8.伪类选择器 div::hover
有两种模型:IE盒子模型、标准盒子模型
IE盒子模型:content部分包含border和padding
标准盒子模型:内容(content)、填充(padding)、边界(margin)、边框(border)
在IE盒子模型中,width 和 height 指的是内容区域+border+padding的宽度和高度。
在标准盒子模型中,width 和 height 指的是内容区域的宽度和高度。增加内边距、边框和外边距不会影响内容区域的尺寸,但是会增加元素框的总尺寸
CSS3中的box-sizing属性:
box-sizing:border-box表示盒模型基于IE的盒模型,width和height决定盒模型的content区、padding区和border区。
box-sizing:content-box表示盒模型基于标准盒模型,width和height只决定盒模型的content区
box-sizing:inherit表示继承自父元素。
1 | /*已知容器的宽高 设置层的外边距*/ |
VUE相关问题
beforeCreate( 创建前 ) => created(创建后)=> beforeMount(挂在前)=> mounted(挂载后)=>
beforeUpdate(数据更新前调用)=> updated(更新后)=> beforeDestroy(实例销毁前)=> destroyed(实例销毁后)
activated(被 keep-alive 缓存的组件激活时调用)
decactived(被 keep-alive 缓存的组件停用时调用)
实现mvvm的双向绑定,是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调
1.加载过程
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
2.子组件更新过程
父beforeUpdate->子beforeUpdate->子updated->父updated
3.父组件更新过程
父beforeUpdate->父updated
4.销毁过程
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
vue组件间通信
①.props 和 $emit
父组间通过props向下传递数据给子组件,子组件通过event给父组件发送消息,实际上就是子组件把自己的数据发送给父组件。
②. $ attrs 和 $ listeners
祖孙间隔代通过$ attrs传递数据,$listeners监听数据的改变
1 | <!-- A组件 --> |
1 | <!-- B组件 --> |
1 | <!-- C组件 --> |
3.provide和 inject
provide 和 inject成对出现,用于父级组件向下传递数据;
父组件中通过provide来提供变量,然后在子组件中通过inject来注入变量。不论子组件有多深,只要调用了inject那么就可以注入provide中的数据。而不是局限于只能从当前父组件的prop属性来获取数据,只要在父组件的生命周期内,子组件都可以调用。
1 | <!-- 父组件 --> |
4.vuex处理组件之间的数据交互
如果业务逻辑复杂,很多组件之间需要同时处理一些公共的数据,这个时候才有上面这一些方法可能不利于项目的维护,vuex的做法就是将这一些公共的数据抽离出来,然后其他组件就可以对这个公共数据进行读写操作,这样达到了解耦的目的
TCP与IP的区别与联系
1.TCP工作于传输层,IP工作于网络层。
2.TCP提供应用进程之间的通信,而IP提供主机之间的通信。
3.TCP以IP为基础,面向应用层提供服务。IP协议为TCP提供服务。IP协议将数据从一台主机发送至另一台主机,TCP则保证了其传输可靠性。
4.TCP是面向连接的,而使用的低层网络可以是无连接的,也可以是连接的,但使用无连接的网络的会使整个网络系统更加灵活