1. var,let,const 的区别
1)var
var定义的变量,没有块的概念,可以跨块访问,不能跨函数访问
var会提升声明
2)let
let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问
3)const
const的行为与let基本相同
唯一的区别是:const是用来定义常量的,而且必须赋值,且不允许被修改;const定义对象里面的属性可以被修改
2. 跨域方式
1. jsonp 6. nginx反向代理
2. cors 7. window.name + iframe
3. postMessage 8. location.hash + iframe
4. websocket 9. document.domain + iframe
5. Node中间件代理
- cors支持所有类型的HTTP请求,是跨域HTTP请求的根本解决方案
- JSONP只支持GET请求,优势在于支持老浏览器,以及可以向不支持cors的网站请求数据
- Node中间件代理 / nginx反向代理,主要是通过同源策略对服务器不加限制
- 日常工作中,cors和nginx用的多
3. webpack
理解:webpack是一个模块打包器,它的主要目标是将JavaScript文件打包在一起,打包后的文件用于在浏览器中使用,但它也能胜任转换(transform),打包(bundle)或包裹(package)任何资源(resource or asset)
核心概念:入口(entry),输出(output),loader,插件(plugin),模式(mode),浏览器兼容性(browser compatibility),环境(environment)
4. websocket的原理
websocket为应用层协议,其定义在TCP/IP协议zhan之上。WebSocket链接服务器的URI以“ws” 或者 “wss” 开头。ws开头的默认TCP端口为80,wss开头的默认端口为443
websocket协议由RFC 6455定义。协议分为两个部分:握手阶段和数据通信阶段。
websocket是基于http协议的,或者说借用了http的协议来完成一部分握手。
- 最初的握手阶段是http协议,握手完成后就切换到websocket协议,并完全与http协议脱离了。
- 建立通讯时,是由客户端主动发起链接请求,服务端被动监听。
- 通讯一旦建立连接后,通讯就是“全双工”模式了。也就是说服务端和客户端都能在任何时间自由得发送数据,非常适合服务端主动推送实时数据得业务场景。交互模式不再是“请求-应答”模式,完全由开发者自行设计通讯协议。
- 通信得数据是基于“帧(frame)”的,可以传输文本数据,也可以直接传输二进制数据,效率高。当然,开发者也就要考虑封包,拆包,编号等技术细节
5. 长轮询
- 含义:客户端发起请求,如果服务的请求没有发生改变,那么就hold住请求,直到服务端的数据发生变更,或者达到了一定的时间就会返回,这样就减少了客户端和服务端不断频繁连接和传递数据的过程,并且不会消耗服务端太多资源
- 原理:采用异步响应的方式实现,Servlet3.0 提供的AsyncContext机制。asyncContext是为了吧主线程返回给tomcat线程池,不影响服务对其他客户端请求,会有线程专门处理这个长轮询,吧长轮询的request的引用在一个集合存起来,用一个或几个线程专门处理一批客户端的长轮询请求,这样就不用为每一个长轮询单独分配线程而导致阻塞,从而大大降低了资源的消耗
6. http了解多少
超文本传输协议,构建与TCP / IP 协议之上,默认端口号为80,处于网络体系结构的最顶层应用层之上,Http协议采用的请求 / 响应的工作方式, Http是无连结无状态的
Q:无连接、无状态?无连接是指限制每次连接只处理一个请求,服务器处理完客户的请求,并收到客户的应答后,即断开连接,可节省传输时间。
无状态是指协议对于事物处理没有记忆能力,服务器不知道客户端是什么状态,即我们给服务器发送Http请求之后,服务器根据请求,会给我们发送数据过来,但是发送完不会记录任何信息,这就表明每个请求是独立的。
Http报文:Http在应用层通过报文的方式来交换数据,分为请求报文和响应报文
Q:请求报文?请求行:声明了请求方法,主机域名,资源路径和协议版本
请求头:包括一些访问的域名,用户代理,Cookie等信息
请求体:Http请求的数据
Q:响应报文?状态行:包括协议版本Version,状态码Status Code,状态码描述
响应头:包括搭建服务器的软件,发送响应的时间,回应数据格式等
响应体:响应的具体数据
7. 怎么理解事件循环
关于异步:
8. 移动端怎么实现1px的分割线
- 利用缩放原理
- 用border-image方法实现
9. 结合防抖,节流,讲一下闭包
- 概念:
闭包是指有权访问另一个函数作用域中的变量的函数
- 特点:
1)两个嵌套关系的函数
2)内部函数使用到外部函数局部变量或参数
3)变量和参数不会被回收
- 闭包的优点:
1)延伸了变量的作用域
2)有效的避免了全局变量污染
3)保护数据安全
- 闭包的缺点:
由于闭包会使函数中的变量保存在内容中,内存消耗很大(内存泄露严重)
解决方法:退出函数之前,将不使用的局部变量删除(销毁闭包)
- 闭包的使用场景
1. 函数节流
规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效//fn是需要被节流的函数 delay是时间 function throttle(fn, delay) { let flag = true return function () { if (!flag) { return //如果开关关闭了,那就直接不执行下边的代码 } flag = false //持续触发的话,run一直是false,就会停止在上边的判断那里 setTimeout(() => { fn.apply(this.aruguments) flag=true //定时器到时间之后,会把开关打开,我们的函数就会被执行 },delay) } }
2. 函数防抖
在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时
实现的关键在于setTimeOut这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现
//fn [function] 需要防抖的函数 //delay [number] 毫秒,防抖期限值 function debounce(fn, delay) { let timer = null //借助闭包 return function () { if (timer) { clearTimeout(timer)//进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件,所以要取消当前的计时 timer=setTimeout(fn, delay) } else { timer=setTimeOut(fn,delay)//进入该分支说明当前并没有在计时,那么就开始一个计时 } } }
10. JS实现继承的方式
- 原型链继承
- 借用构造函数继承
- 组合继承
- 原型式继承
- 寄生式继承
- 寄生组合式继承
- ES6,Class实现继承
11. 如果在握手过程中key被第三方拦截,https怎么保证它的安全?
https并非是应用层一个新的协议,通常HTTP直接和TCP通信,HTTPS则先和安全层(SSL / TLS) 通信,然后安全层再和TCP通信
SSL / TLS 协议就是为解决HTTP的问题而生的:
1)所以信息都是加密传输,无法被窃听2)配备身份验证,防止身份被冒充
3)具有校验机制,一旦被篡改,通信双方会立刻发现
12. https是对公钥加密还是私钥加密
公钥加密,私钥解密
13. 回流重绘的优化
Q:什么是重绘?
当渲染树中的一些元素需要更新属性,而这些属性只影响元素的外观,风格,而不影响布局,则为重绘
Q:什么是回流?
当渲染树中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建,这就称为回流。每个页面至少需要一次回流,就是在页面第一次加载的时候,这时候是一定会发生回流的,因为要构建渲染树。
引发问题:回流的代价要远高于重绘,回流会造成重绘,重绘不一定回流。回流浏览器需要重新渲染页面,从而影响性能。
如何优化?
1)将频繁回流的DOM元素作为一个独立的图层,那么这个DOM元素的回流只影响这一个图层2)避免使用触发回流的CSS属性
14. TCP慢启动
一、什么是拥塞?什么是拥塞控制?
- 拥塞:随着网络中的主机增加其发送速率并使网络变得十分拥塞,此时会经常发生丢包现象,导致网络得传输效率急剧降低。分组得超时重传通常被作为网络拥塞的标志。
- 如果不对网络拥塞进行控制,整个网络的吞吐量将随着输入负荷的增大而下降,降低网络的传输效率,如下图:
二、TCP的4种拥塞控制算法(慢开始、拥塞避免、快重传、快恢复)
- 这里做一个情况假设:
1. 数据是单向传送的,另一个方向只传输确认
2. 接收方的总是有足够大的缓冲区,因此发送方的发送窗口仅由网络的拥塞程度决定,事实上发送窗口的大小由拥塞窗口和接收方的接收窗口大小共同控制,也即发送窗口 = min[接收窗口,拥塞窗口];
3.以最大报文段MSS的个数作为讨论单位,而不是以字节为单位
- 发送方维护一个叫做拥塞窗口cwnd(congestion window)的状态变量,其值取决于网络的拥塞变化,动态变化
1. 拥塞窗口的维护原则:只要网络没有出现拥塞,cwnd就增大一些;但只要网络出现拥塞,拥塞窗口就减小一些
2. 以分组发生超时重传作为发生网络拥塞的依据
- TCP还维护一个慢开始门限ssthresh状态变量
1. 当cwnd < ssthresh 时,使用慢开始算法
2. 当cwnd > ssthresh 时,使用拥塞避免算法
3. 当cend = ssthresh 时,既可以使用慢开始算法,也可以使用拥塞避免算法
- 当发生数据正常丢包,但又不是网络拥塞时,使用快重传算法和快恢复算法
1. 如何判断是发生了正常丢包而不是网络拥塞呢?
2. 当发送方连续接收到3次重复确认时,说明这网络不拥塞,只是正常丢包了
15. new方法的实现原理
1)新生成对象:new关键字首先会创建一个空对象
2)链接到原型:将这个空对象的原型对象指向构造函数的原型属性,从而继承原型上的方法
3)绑定this:将this指向这个空对象,执行构造函数中的代码,以获取私有属性
4)返回新对象:如果构造函数返回了一个对象res,就将该返回值res返回,如果返回值不是对象,就将创建的对象返回
16. 怎么理解面向对象和面向过程
面向对象基本概念:将现实问题构建关系,然后抽象成类(class),给类定义属性和方法后,再将类实例化成实例(instance)通过访问实例的属性和调用方法来进行使用
面向过程基本概念:以过程为中心的编程思想,都是以什么正在发生为主要目标进行编程。不同于面向对象的时谁在受影响,与面向对象明显不同的就是封装、继承、类。
优劣分析:
面向对象 优:易维护,易复用,易扩展,可降低耦合,使系统更灵活 劣:性能比面向过程差 面向过程 优:性能比面向对象好,因为类调用时需要实例化,消耗资源多 劣:不易维护,不易复用,不易扩展
17. 怎么理解进程和线程
- 本质区别:进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位
- 包含关系:一个进程至少有一个线程,线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程
- 资源开销:每个进程都有独立的地址空间,进程之间的切换会有较大的开销;线程可以看作轻量级的进程,同一个进程内的线程共享进程的地址空间,每个线程都有自己独立的运行栈和程序计数器,线程之间切换的开销小
- 影响关系:一个进程崩溃后,在保护模式下其他进程不会被影响,但是一个线程崩溃可能导致整个进程被操作系统杀掉,所以多进程比多线程健壮
18. 进程之间的通信方式
无名管道,高级管道,有名管道,消息队列,信号量,信号,共享内存,套接字
19. 同步请求和异步请求的区别
同步就是这个方法请求完成后,再执行下一个请求方法
异步就是在请求这个方法的时候,可以在当前的页面写一个ajax请求后台查询对应数据,这就在请求页面同时也在请求数据返回其数据
20. 传输层的作用
传输层是整个网络体系结构中关键层次之一,主要负责向两个主机中进程之间的通信提供服务。
21. 如果连接客户端出现故障,服务器会怎么做?
TCP设有一个保活计时器。客户端如果出现故障,服务器不会一直等待下去,服务器每收到一次客户端的请求后都会复位这个计时器,时间通常是设置为两个小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,每隔7s发一次,若一连发送10个探测报文仍没有反应,服务器就认为客户端出了状况,接着就关闭连接。
22. 说一下你知道的设计模式
- 创建型模式:工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式
- 结构型模式:适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式
- 行为型模式:策略模式,模板方法模式,观察者模式,迭代子模式,责任链模式,备忘录模式,命令模式,状态模式,访问者模式,中介者模式,解释器模式
23. 堆和栈的区别
- 申请方式——栈由系统自动分配,堆是人为申请开辟
- 申请大小——栈获得的空间极小,堆获得的空间较大
- 申请效率——栈由系统自动分配,速度极快,堆一般速度比较慢
- 存储内容——栈在调用函数时,函数调用语句的下一条可执行语句的地址第一个进栈,然后函数的各个参数进栈,其中静态变量不入栈,堆一般在头部用一个字节存放堆的大小,堆中的具体内容是人为安排
- 底层不同——栈是连续空间,堆是不连续空间
24. 说一下Promise
Promise是异步编程的一种解决方案,它有三种形态:pending(等待态), resolved(成功态), rejected(失败态), 状态一旦改变,就不会再变
它有两个回调,.then() 和 .race(),从 pending ——> resolved 后,执行 .then() 回调,从 pending ——> rejected 后,执行 .catch() 回调它有两个方法,.all() 和 .race() ,入参都是一个promise数组,all是所有的都成功返回成功的数组,有一个失败即返回失败的状态,race是返回最先完成的状态
缺点:
- promise一旦新建就会立即执行,无法中途取消
- 如果不设置回调函数,promise内部抛出的错误,不会反应到外部
- 当它处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)
25. 前端性能优化
- 压缩图片,使用CDN
- 减少http请求,图片懒加载
- CSS写在头部,JS写在底部
- JS优化(防抖,节流,事件委托,减少重排重绘);CSS优化(提取公共样式,减少选择器嵌套,精灵图)
26. 知道发布订阅模式吗?面试官:我把类写好,调用方法也写好,实现这个类就可以了
给定代码:
class EventEmitter{ } const event = new EventEmitter() const successCallback = () => { console.log('123') } //绑定事件 event.addEventListener('success', successCallback) //触发事件 event.dispatchEvent('success') //删除事件 event.removeEvent('success', successCallback)
我的实现:
class EventEnmitter { constructor() { this.event = {} } addEventListener(name, fn){ if (!this.event[name]) { this.event[name]=[fn] } else { this.event[name].push(fn) } } dispatchEvent(name) { if (this.event[name].length != 0) { this.event[name].forEach((e) => { e.call(this) }) } } removeEvent(name, fn) { if (!fn) { this.event[name].length=0 } if (this.event[name]) { this.event[name].filter((e) => { return e != fn }) } } }
27. git的基本操作有哪些
clone, branch, checkout, add, commit, pull, push, merge, reset, revert
28. 用过哪些html5标签
header, footer, article, section, aside, nav, main, video, audio, canvas
29. vuex的工作流程
vuex的工作流程就是:
- 通过dispatch去提交一个actions
- actions接收到这个事件之后,在actions中可以执行一些异步 | 同步操作,根据不同的情况去分发给不同的mutations
- actions通过commit去触发mutations
- mutations去更新state数据,state更新之后,就会通知vue进行渲染
30. 用过keep-live吗?
keep-alive 是 vue 的一个内置组件,可以实现组件的缓存,当组件切换时,不会对当前组件进行卸载
31. websocket 和 http 的区别
- websocket时双向通信协议,模拟socket协议,可以双向发送或接收信息,而HTTP是单向的
- websocket是需要浏览器和服务器握手进行建立连接的,而HTTP是浏览器发起向服务器的连接
32. onclick 和 addEventListener 的区别
- addEventListener可以对一个元素绑定多个事件,执行顺序由上至下;而onclick用同一个元素只能绑定一个事件,如果有多个,后面的事件会覆盖前面的事件
- addEventListener第三个参数为布尔值,默认false,执行冒泡机制,若为true,执行捕获
- addEventListener对任何DOM元素都是有效的,而不仅仅只对HTML元素有效
- addEventListener注册事件时不需要写on,而onclick方式则必须加on
- 在移除事件上,onclick使用指针指向null(document.onclick = null);而addEventListener则使用独有的移除方法removeListener
- addEventListener为DOM 2级事件绑定,onclick为DOM 0级事件绑定
- IE 6 7 8 只能使用attachEvent,无addEventListener
33. ES6模块加载和CommonJS加载的原理
- CommonJS模块的加载原理:
CommonJS模块就是一个脚本文件,require命令第一次加载该脚本时就会执行整个脚本,然后内存中生成该模块的一个说明对象- ES6模块的加载原理:
ES6模块时动态引用,遇到模块加载命令import时不会执行模块,只是生成一个指向被加载模块的引用,需要开发者保证真正取值时能够获取到值,只要引用是存在的,代码就能执行
34. ES6的箭头函数有什么特点?
- 只能先定义后调用
- 没有arguments,但可以使用剩余参数
- 不能当作构造函数,因为箭头函数没有自己的this
- 当只有一个形参时可以省略圆括号
- 当只有一条语句且该语句会作为返回值返回时,可以省略花括号及return关键字
- 箭头函数的this指向依赖外层函数中的this指向,与当前调用者没有关系
35. promise 和 callback 的区别
回调函数:函数当参数,传递另一个函数
Promise:异步编程的一种解决方案,可取代callback;promise构造函数,比传统的回调更合理更强大
36. 什么是回调地狱?
从多层嵌套,为实现代码顺序执行而出现的一种操作,它会造成代码可读性变差,后期不好维护
37. JavaScript函数传参是传递值还是引用?(值)
38. 值类型和引用类型的区别
值类型的变量直接存储数据,而引用类型的变量持有的是数据的引用,数据存储在数据堆中
39. 什么是实参和形参
- 形式参数:在函数定义中出现的参数,可以看作是一个占位符,它没有数据,只能等到函数被调用时接收传递进来的参数
- 实际参数:函数被调用时给出的参数,包含实实在在的数据,会被函数内部的代码使用
40. 解析URL(代码)
JS解析URL,将如下URL
const url = 'https://www.baidu.com/m?f=8&ie=utf-8&rsv_bp=1&tn=monline_3_dg&wd=session'
解析为
{ f: '8', ie: 'utf-8', rsv_bp: '1', tn: 'monline_3_dg', wd: 'session' }
方法一:利用splice分割+循环依次取出
function queryURLparams(url) { let obj = {} if (url.indexOf('?') < 0) return obj let arr = url.split('?') url = arr[1] let array = url.split('&') for (let i = 0; i < array.length; i++){ let arr2 = array[i] let arr3 = arr2.split('=') obj[arr[0]]=arr3[1] } return obj } console.log(queryURLparams(url));
方法二:正则+...argfunction queryURLparamsRegEs6(url) { let obj = {} let reg = /([^?=&]+)=([^?=&]+)/g url.replace(reg, (...arg) => { obj[arg[1]]=arg[2] }) return obj }
41. 什么是最大堆和最小栈
最大堆:所有的节点都大于等于它的子节点
最小堆:所有的节点都小于等于它的子节点
42. 异步与多线程的区别与联系
共同点:
异步和多线程两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性
不同点:
- 线程不是一个计算机硬件功能,而是操作系统提供的一种逻辑功能,线程本质上是进程上一段并发运行的代码,所以线程需要操作系统投入CPU资源来运行和调度
- 异步操作无需额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量,减少了死锁的可能
43. 简述MVC框架
一、 mvc(mode view controller)是什么?
- m指业务代码,v指用户界面,c指控制器
- 使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现方式
- 是一种软件设计模式,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚焦到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑
- MVC被独特的发展起来用于映射传统的输入,处理和输出功能在一个逻辑的图形化用户界面的结构中
二、基于B/S模型,MVC框架如下:
- 用户发起request请求
- 控制器请求模型处理
- 模型将处理结果返回
- 控制器将请求结果发送给视图
- 控制器得到视图结果将响应返回给用户
三、常见的MVC框架有struct2和spring
四、MVC优点
- 耦合性低
- 重用性高
- 生命周期成本低
- 可维护性高
- 有利软件工程化管理
什么是Spring MVC?Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,Controller分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。
44. CSS中常用的选择器
一、基础选择器
- 标签选择器
- 类选择器
- id选择器
- 通配符选择器
二、复合选择器
- 后代选择器
- 子选择器
- 并集选择器
- 伪类选择器
45. scpoed的原理
scoped属性的效果是通过PostCss实现的
为组件实例生成一个唯一标识,给组件中的每个标签对应的dom元素添加一个标签属性,给<style scoped>中的每个元素选择器的最后一个选择器添加一个属性选择器
46. 后代选择器是什么
是一种多个用空格分隔的选择器
47. 怎么隐藏一个元素
- display: none
- visibility: hidden
- opacity: 0
- transform: scale(0,0)
- width 或 height 为 0
- z-index 负值
- 绝对定位移出视口
48. opscity: 0 和 visibility: hidden 的区别
opscity: 0 能触发点击事件
visibility: hidden 不能触发点击事件
49. 数组的方法有哪些
join,split,pop,push,shift,unshift,reverse,sort,concat,slice,splice,indexOf,lastIndexOf,forEach,map,filter,find,findIndex,every,reduce
50. 怎么清空一个数组
设为[],长度为0,splice(0, length)