前端面试无非包括css、js、框架、项目等几大方面。以下是自己在面试过程中关于js被问到的问题,有的偏基础,也有比较深入的,理解这些问题不仅仅有助于面试,最重要的是能够在实际过程中尽可能少开发些BUG。现在记个笔记,暂时没有分类,想到哪个记哪个。。
一、url输入浏览器后干了些什么事情?
1.DNS(Domain Name System, 域名系统) 解析
- DNS解析的过程就是寻找哪台机器上有你真正需要的资源过程。
- 当我们在浏览器地址栏中输入一个地址时,例如:baidu.com,其实不是百度网站真正意义上的地址,因为互联网上每一台计算机的唯一标识是他的IP地址,但是IP地址并不方便记忆。
- 所以互联网设计者需要在用户的方便性与可用性做一个权衡,这个权衡就是一个网址到IP地址的转换,这个过程就是DNS解析
- 它(DNS解析)实际上充当了一个翻译的角色,实现了网址到IP地址的转换。当然如果你直接输入的是另一台电脑的IP地址来访问,那么不存在这一步
2.TCP连接(三次握手)
知道了服务器的IP地址,就开始和服务器简历连接了。连接的建立需要经历三次握手(两个在)
- 第一次握手: 建立连接时,客户端发送syn包(syn=j)到服务器,并进入
SYN_SENT
,等待服务器确认. - 第二次握手: 服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己发送一个SYN包(syn=k),即
SYN+ACK
包,此时服务器进入SYN_RECV
状态 - 第三次握手: 客户端收到服务器的
SYN+ACK
包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED
(TCP链接成功状态),完成三次握手
3.发送HTTP请求
当服务器与主机建立了链接以后,注意开始和服务器进行通信.网页请求是一个单向请求的过程.即一个主机向服务器请求数据,服务器返回相应的数据的过程.浏览器根据URL内容生成HTTP请求,HTTP请求报文是由三部分组成:请求行,请求报头,请求正文.
4.服务器处理请求并返回HTTP报文
服务器接到请求后,会根据HTTP请求中的内容来决定如何获取相应的HTML文件,服务器得到的HTML文件发送给浏览器。HTTP响应报文也是由三部分组成:状态码,响应头,响应报文
状态码
- 1xx: 指示信息,标示请求已接收,急需处理.
- 2xx: 成功信息,标示请求已被成功接收,理解,接收
- 3xx: 重定向,要完成请求必须进行更进一步的操作
- 4xx: 客户端错误,请求有语法错误或请求无法实现
- 5xx: 服务器端错误,服务器未能实现合法的错误
响应头
- 常见的响应头字段有:Server,Connection..
响应报文
- 服务器返回给浏览器的文本信息。HTML,CSS,JS,图片等文件就放在这一部分
5.浏览器解析渲染页面
在浏览器还没有在完全接收HTML文件时便开始渲染网页
在执行HTML中的代码时,根据需要浏览器会继续请求图片,CSS,JavaScript等文件
6.连接结束
7.四次回收连接
- 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部.FIN=1,其序列号为seq=u(根据前面已经传过来的数据的最后一个序号+1)。此时客户端进入FIN-WAIT-1(终止等待1)状态。TCP规定,FIN报文段即使不携带数据,也要消耗一个序号
- CLOSE-WAIT状态持续期间。服务器收到连接释放报文,发出确认报文ACK=1,ack=u+1,并且带上自己的序列号seq=v此时,服务端就加入了CLOSE-WAIT(关闭-等待)状态。这时连接处于半关闭状态,客户端已经没有数据要发送了。但是服务器若发送数据,客户端仍然接收。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间
- 客户端收到服务器的确认请求后,就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接收服务器发送的最后数据)
- 服务器将最后的数据发送完毕后,就像客户端发送连接释放报文:FIN=1,ack=u+1。由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认
- 客户端收到服务器的连接释放报文后,必须发出确认:ACK=1,ack=w+1。而自己的序列号是seq=u+1,此时客户端进入了TIME-WAIT(时间等待)状态。注意此时TCP连接没有释放,必须经过2MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态
- 服务器只要收到客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次TCP连接。可以看到,服务器结束TCP连接的时间比客户端要更早一些
8.关于TCP三次握手及相关面试题可参考:https://www.cnblogs.com/bj-mr-li/p/11106390.html
二、http协议了解多少?
- 只是了解下的话这篇文章足够:https://www.cnblogs.com/li0803/archive/2008/11/03/1324746.html
- PS:各种请求方式及其含义
请求方式 | 含义 |
---|---|
GET | 请求获取Request-URI所标识的资源 |
POST | 在Request-URI所标识的资源后附加新的数据 |
PUT | 请求服务器存储一个资源,并用Request-URI作为其标识 |
DELETE | 请求服务器删除Request-URI所标识的资源 |
HEAD | 请求获取由Request-URI所标识的资源的响应消息报头 |
TRACE | 请求服务器回送收到的请求信息,主要用于测试或诊断 |
CONNECT | 保留将来使用 |
OPTIONS | 请求查询服务器的性能,或者查询与资源相关的选项和需求 |
三、webpack打包
https://segmentfault.com/a/1190000016068450
四、性能优化
性能优化太宽泛了,我总结了下自己在实际开发中用到的优化手段,大概有以下几个方面:
- 图片--雪碧图、svg雪碧图、webpack插件优化、第三方工具压缩图片
- 三方库优化--按需(lodash、echarts)、懒加载
- CDN引入
- HTML--语义化标签
- JS/TS--代码精简-公共函数封装、页面优化-节流/防抖等
五、冒泡排序法
- 冒泡排序(更多js排序算法:https://www.cnblogs.com/ybygb-geng/p/9355425.html)
原理:把一个数组中的每一个数从前往后依次进行比较,然后根据大小交换位置,每一轮的比较都确定出一个当轮比较的最大值,最终实现数组的大小排序
var arr = [4,23,100,9,7,49,36,57];
console.log("原始数据:"+arr);
for (var i = 0; i < arr.length-1; i++) { //确定轮数
for (var j = 0; j < arr.length-i-1; j++) { //确定每次比较的次数
if (arr[j] > arr[j+1]) {
tem = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tem;
}
}
console.log("第"+i+"次排序"+arr)
}
console.log("最终排序:"+arr)
console控制台打印如下:
六、一行代码实现数组去重
方法一:ES6中Array新方法Array.from
和Set
数据结构。 set的成员都是唯一的 ,其构造函数可以接受一个数组作为参数
let array = Array.from(new Set([1, 1, 1, 2, 3, 2, 4]));
console.log(array);
// => [1, 2, 3, 4]
方法二:使用三方库,如:
lodash
var list= [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
list = lodash.uniqWith(list, lodash.isEqual)
// => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
七、解构赋值
- 解构赋值是对赋值运算符的扩展。
- 它针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。
- 在代码书写上简洁且易读,语义更加清晰明了;也方便了复杂对象中数据字段获取。
- 在解构中,有两部分参与:解构的源,解构赋值表达式的右边部分;解构的目标,解构赋值表达式的左边部分
数组模型的解构(Array)
// 基本
let [a, b, c] = [1, 2, 3]; // a = 1 // b = 2 // c = 3
// 可嵌套
let [a, [[b], c]] = [1, [[2], 3]]; // a = 1 // b = 2 // c = 3
// 可忽略
let [a, , b] = [1, 2, 3]; // a = 1 // b = 3
// 不完全解构
let [a = 1, b] = []; // a = 1, b = undefined
// 剩余运算符
let [a, ...b] = [1, 2, 3]; //a = 1 //b = [2, 3]
/* 字符串等 */
// 在数组的解构中,解构的目标若为可遍历对象,皆可进行解构赋值。可遍历对象即实现 Iterator 接口的数据。
let [a, b, c, d, e] = 'hello'; // a = 'h' // b = 'e' // c = 'l' // d = 'l' // e = 'o'
// 解构默认值
let [a = 2] = [undefined]; // a = 2
// 当解构模式有匹配结果,且匹配结果是 undefined 时,会触发默认值作为返回结果。
let [a = 3, b = a] = []; // a = 3, b = 3
let [a = 3, b = a] = [1]; // a = 1, b = 1
let [a = 3, b = a] = [1, 2]; // a = 1, b = 2
// a 与 b 匹配结果为 undefined ,触发默认值:a = 3; b = a =3
// a 正常解构赋值,匹配结果:a = 1,b 匹配结果 undefined ,触发默认值:b = a =1
// a 与 b 正常解构赋值,匹配结果:a = 1,b = 2
对象模型的解构(Object)
// 基本
let { foo, bar } = { foo: 'aaa', bar: 'bbb' }; // foo = 'aaa' // bar = 'bbb'
let { baz : foo } = { baz : 'ddd' }; // foo = 'ddd'
// 可嵌套可忽略
let obj = {p: ['hello', {y: 'world'}] }; let {p: [x, { y }] } = obj; // x = 'hello' // y = 'world' let obj = {p: ['hello', {y: 'world'}] }; let {p: [x, { }] } = obj; // x = 'hello'
// 不完全解构
let obj = {p: [{y: 'world'}] }; let {p: [{ y }, x ] } = obj; // x = undefined // y = 'world'
// 剩余运算符
let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}; // a = 10 // b = 20 // rest = {c: 30, d: 40}
// 解构默认值
let {a = 10, b = 5} = {a: 3}; // a = 3; b = 5; let {a: aa = 10, b: bb = 5} = {a: 3}; // aa = 3; bb = 5;
八、js原型链
- 简单一行代码表示(详见我另一篇文章js原型及原型链):
function Person() {};
var p = new Person();
p.__proto__ === p.contructor.prototype
// p.contructor就是Person,所以上述代码也可以是:
p.__proto__ === Person.prototype
九、 js是同步还是异步,单线程还是多线程,操作原理
JavaScript是一门单线程语言,在最新的HTML5中提出了Web-Worker,但JavaScript是单线程这一核心仍未改变。所以一切JavaScript版的”多线程”都是用单线程模拟出来的。
- 同步和异步任务分别进入不同的执行”场所”,同步的进入主线程,异步的进入Event Table并注册函数。
- 当指定的事情完成时,Event Table会将这个函数移入Event Queue。
- 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。
- 上述过程会不断重复,也就是常说的Event Loop(事件循环)。
关于Event Loop: https://segmentfault.com/a/1190000016278115
十、数据结构了解吗?讲一下链表?
数据结构:数组、栈( 后进先出)、队列Queue( 先进先出)、链表(Linked List) https://www.cnblogs.com/nayek/p/11924204.html
十一、跨域如何解决
纯前端解决: https://segmentfault.com/a/1190000000718840
后端配合解决: https://segmentfault.com/a/1190000003693381
十二、ajax的过程、xmlhttprequest对象
AJAX的原理及实现步骤 https://blog.csdn.net/weixin_39194176/article/details/80933777
十三、js实现图片轮播(主要思路?)
十四、js实现DNA链,如下图(主要思路?)
- 生成两个box(容器,上下分为两部分),分别给每个容器设置3D模式,动画等属性
- 在两个box中生成一定数量的点
- 把box加入body中
关键知识点:
- transform-style: preserve-3d; // 设置3D转化模式
- animation相关
JS生成动画