面试题库总结
- 1.谈谈你对web标准的理解?
- 2.网页加载流程?
- 3.客户端与服务器流程?
- 4.浏览器兼容性产生原因?
- 5.浏览器组成?
- 6.CSS选择符有哪些?
- 7.Display与visibility有何异同?
- 8.页面的绝对定位和相对定位?
- 9.BOM的理解?
- 10.DOM的理解?
- 11.BOM与DOM的关系?
- 12.http和https?
- 13.冒泡排序
- 14.选择排序
- 15.插入排序
- 16.利用random()通过函数返回值
- 17.GET和POST有什么区别?
- 18.GET和POST的请求过程
- 19.栈和队列的区别
- 20.栈和堆的区别
- 21.CSS中link和@import的区别是什么?
- 22.浏览器跨域
- 23.TCP及UDP请求
- 24.浏览器缓存cookie,sessionStorage,localStorage
- 25.http缓存以及http请求
- 26.浏览器的多线程
- 27.生命周期,生命周期函数
- ==28.Vue的数据双向绑定实现基本原理(MVVM模型)==
- 29.watch
- ==30.Vue渲染/更新流程==
- 31.webpack(模块打包器)模块化思想
- 32.CSS盒模型
- 33.CSS中box-sizing
- 34.布局position,flex
- 35.JS的二叉树先序遍历算法
- 36.ES6的特性(let,const,模板字符串,箭头函数,解构,类等)
- 37.promise
- 38.原型链
- 39.利用迭代器和生成器写斐波那契数列
- 40.symbol
1.谈谈你对web标准的理解?
Web标准是一系列标准的集合,网页主要由三部分组成:结构,表现和行为。在页面body里面我们写入的标签都是为了页面的结构。表现包括CSS样式,通过CSS样式使得页面的结构标签更具美感。行为指的是页面所具有的交互的行为,同时页面结构也会发生变化。
2.网页加载流程?
在浏览器地址栏内输入URL后,会
(1)查找浏览器缓存
(2)DNS解析,查找该域名对应的IP地址,重定向,发送第二个GET请求(3)进行HTTP协议会话
(4)客户端发送报头
(5)服务器回馈报头
(6)HTML文档开始下载
(7)文档树建立,根据标记请求所需指定类型的文件
(8)文件显示
3.客户端与服务器流程?
客户端通过指定的访问地址获得服务器资源到服务器,服务器使用HTTP协议的通信发送到客户端。
4.浏览器兼容性产生原因?
网页浏览器标准只规定了接口,并没有接口实现的详细规范,使得各浏览器对相同的功能使用了不同的实现方法。浏览器版本实现上的差异,老版本浏览器不支持新的技术。
5.浏览器组成?
6.CSS选择符有哪些?
Id选择器(#);类选择器(.);标签选择器(div,h1,p);
相邻选择器(h1+p);子选择器(ul>li);后代选择器(li a);
通配符选择器();属性选择器([title]{color:red});伪类选择器(a:hover)
7.Display与visibility有何异同?
Display可以有很多值,visibility只有两个常用值:visible,hidden。
当display为none,visibility为hidden时都会隐藏元素。但display会隐藏掉元素空间,visibility会保留元素空间。
8.页面的绝对定位和相对定位?
相对定位relative:相对定位是将自己在原来文档流中的位置作为参照物。相对定位之后的对象并没有完全从文档流中脱离,原来的位置会进行保留,偏移后的对象会把其他的层遮罩住。
绝对定位absolute:被绝对定位的对象将会从文档流中脱离。绝对定位的对象相对于距离自己最近的设置了相对定位或者绝对定位的父对象进行定位,如果父对象没有定位,则相对于HTML根元素定位。
9.BOM的理解?
BOM即浏览器对象模型:主要用于管理浏览器窗口之间的通讯,由一系列相关的对象构成,并且每个对象都提供了很多方法和属性。Window对象是BOM中所有对象的核心,是BOM中所有对象的父对象。
10.DOM的理解?
DOM即文档对象模型:通过创建节点树来表示文档,是应用程序的API接口,描述了处理网页内容的方法和接口,从而使得开发者对文档的内容和结构具有空前的控制力,用DOM API可以轻松的删除,添加和替换节点以及设置文档中的标签的属性。
11.BOM与DOM的关系?
BOM负责跟浏览器框架打交道,DOM负责浏览器内容Document打交道。操作网页时DOM进行访问,BOM来作为载体承接我们所看到的内容。
12.http和https?
- 基本概念
http:超文本传输协议,是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。
https:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。https协议的主要作用是建立一个信息安全通道,来确保数组的传输,确保网站的真实性。 - 区别
1.http是超文本传输协议,信息是明文传输,https则是具有安全性的SSL加密传输协议。
2.https协议需要ca证书,费用较高。
3.使用不同的链接方式,端口也不同,一般而言,http协议的端口为80,https的端口为443.
4.http的连接很简单,是无状态的;https协议是由SSL+HTTP协议构建的可进行加密传输,身份认证的网络协议,比http协议安全。
13.冒泡排序
比较相邻的元素,如果前者大于后者就交换。
var sortArray=function (nums){
for(let i=0;i<nums.length;i++){
for(let j=0;j<nums.length-i-1;j++){
if(nums[j]>nums[j+1]){
swap(nums,j,j+1);
}
}
}
return nums;
}
14.选择排序
首先在未排序序列中找到最小元素,存放到排序序列的起始位置,再从剩余未排序元素中继续寻找最小元素,然后放到已排序序列的末尾,以此重复。
var sortArray = function (nums) {
for (let i = 0; i < nums.length; i++) {
let min = i;
// 已排序区间 [0, i) ,未排序区间 [i+1 , len)
// 遍历 i+1 之后的元素找到最小元素的索引
for (let j = i + 1; j < nums.length; j++) {
if (nums[j] < nums[min]) {
min = j;
}
}
swap(nums, i, min);
}
return nums;
};
15.插入排序
每次将一个数字插入一个有序的数组里,成为一个长度更长的有序数组。
交换元素实现
var sortArray = function (nums) {
// 从下标为1的元素开始选择合适的位置插入,因为下标为0的只有一个元素,默认是有序的
// 已排序区间 [0, i) ,未排序区间 [i , len)
// 将 nums[i] 插入到区间 [0, i) 使之成为有序数组
for (let i = 1; i < nums.length; i++) {
// 从右往左遍历
for (let j = i; j > 0 && nums[j] < nums[j - 1]; j--) {
// 只要nums[j]比前一个元素nums[j-1]小,就交换这两个元素
swap(nums, j, j - 1);
}
}
return nums;
};
16.利用random()通过函数返回值
编写一个函数randomFrom(lower, upper)返回一个大于或等于lower且小于或等于upper的随机整数。
function randomFrom(lower, upper) {
var sub = upper - lower + 1;
return Math.floor(Math.random() * sub + lower);
}
var num = randomFrom(2, 10);
console.log(num);
17.GET和POST有什么区别?
HTTP是基于TCP/IP的关于数据如何在万维网中如何通信的协议。而GET和POST方法只是HTTP协议为了不同分工而规定的两种请求方式。
- 作用不同:GET多用于从服务端获取资源,POST一般用来向服务端提交资源。
- 安全性:GET传输的参数是直接暴露在URL上的,所以GET不能用来传递敏感信息。
- 参数长度限制不同:GET传送的数据量较小,不能大于2KB;POST传送的数据量较大,一般被默认为不受限制。
- 编码方式不同:GET请求只能进行URL编码;POST支持多种编码方式。
18.GET和POST的请求过程
-
GET请求过程:
1.浏览器请求TCP连接(第一次握手)
2.服务器答应进行TCP连接(第二次握手)
3.浏览器确认,并发送GET请求头和数据(第三次握手,这个报文比较小,所以HTTP会在此时进行第一次数据发送)
4.服务器返回200 OK响应 -
POST请求
1.浏览器请求TCP连接(第一次握手)
2.服务器答应进行TCP连接(第二次握手)
3.浏览器确认,并发送POST请求头(第三次握手,这个报文比较小,所以HTTP会在此时进行第一次数据发送)
4.服务器返回100 Continue响应
5.浏览器发送数据
6.服务器返回200 OK响应
19.栈和队列的区别
- 栈的插入和 删除操作都是在一端进行的,而队列的操作却是在两端进行的
- 队列先进先出,栈先进后出
- 栈只允许在表尾一端进行插入和删除,而队列只允许在表尾一端进行插入,在表头一端进行删除
20.栈和堆的区别
- 栈区:由编译器自动分配释放,存放函数的参数值,局部变量的值等
- 堆区:一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收
- 堆:堆可以被看做是一棵树,例如堆排序
- 栈:是一种先进后出的数据结构
21.CSS中link和@import的区别是什么?
- link属于HTML标签,而@import是CSS提供的
- 页面被加载时,link会同时被加载,而@import被引用的CSS会等到引用它的CSS文件被加载完再加载
- @import只在IE5以上才能识别,而link是HTML标签,无兼容问题
- link方式的样式的权重高于@import得到权重
22.浏览器跨域
跨域问题来源于浏览器的同源策略,浏览器为了提高网站的安全性,在发送ajax请求时,只有在当前页面地址与请求地址的协议+域名+端口号相同时才允许访问,否则会被拦截。
- 协议:即通信协议,比如我们现在常见的http和https,如果当前页面地址使用http协议,请求的地址使用https协议,那么这个请求就存在跨域问题。
- 域名:即网站网址,如baidu.com,360.com就存在跨域。
- 端口号:即域名对应的服务器的监听端口,这个我们一般是看不到的,因为一般服务器都使用80端口,浏览器默认80端口,所以不需要在域名后再写出端口号。
常用的解决跨域的方法有使用代理(nginx),CORS,jsonp。
23.TCP及UDP请求
TCP/IP通信数据流:
TCP:(网页注册账号,转账)
1.TCP提供IP环境下的数据可靠传输,它提供的服务包括数据传输流,可靠性和多路复用等,通俗说就是它是事先为所发送的数据开辟出连接好的通道,然后再进行数据发送。
2.面向连接的TCP:一个TCP连必须要经过三次”对话“才能建立起来(在吗?在。发过去了,接收一下。)
UDP:(QQ消息,手机信息)
1.UDP则不为IP提供可靠性,流控或差错恢复功能。
一般来说,TCP对用的是可靠性要求高的应用,而UDP对应的是可靠性要求低,传输经济的应用。
2.面向非连接的UDP:非连接表示不管对方状态就直接发送。UDP适用于一次只传送少量数据,对可靠性要求不高的应用环境。因为UDP没有连接的过程,所以它的通信效率高,但它的可靠性不如TCP高。
24.浏览器缓存cookie,sessionStorage,localStorage
- cookie
特性:
1.兼容各种浏览器
2.每次都会和后台交互
3.可设置过期时间 - sessionStorage
特性:
1.H5新增特性,不兼容低版本浏览器
2.本地存储,不会每次和后台交互
3.会话关闭,缓存失效 - localStorage
特性:
1.H5新增特性,不兼容低版本浏览器
2.本地存储,不会每次和后台交互
3.本地缓存,除非手动删除,否则一直存在
25.http缓存以及http请求
常见的http缓存只能缓存get请求响应的资源,对于其他类型的响应则无能为力。
优点:
1.减少了冗余的数据传输,节省了网费
2.缓解了服务器的压力,大大提高了网站的性能
3.加快了客户端加载网页
http缓存可分为强制缓存和协商缓存。
1.强制缓存:在缓存数据未失效的情况下,就会直接使用浏览器的缓存数据,不会再向服务器发送任何请求。
2.协商缓存:当第一次请求时不走强缓存,那么浏览器第二次请求时就会与服务器进行协商,与服务器端对比判断资源是否进行了修改更新,如果服务器端的资源没有修改,那么就会返回304状态码,告诉浏览器可以使用缓存中的数据,这样就减少了服务器的数据传输压力;如果数据有更新就会返回200状态码,服务器就会返回更新后的资源并且将缓存信息一起返回。
26.浏览器的多线程
- js引擎线程(js引擎有多个线程,一个主线程,其它的后台配合主线程)
作用:执行js任务(执行js代码,用户输入,网络请求) - ui渲染线程
作用:渲染页面(js可以操作dom,影响渲染,所以js引擎线程和ui线程是互斥的,js执行时会阻塞页面的渲染) - 事件触发线程(当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待js引擎的处理)
作用:控制交互,响应用户 - http请求线程
作用:ajax请求等 - 定时触发器线程
作用:setTimeout和setInteval - 事件轮询处理线程(有的文章中没有这一个)
作用:轮询消息队列,event loop
27.生命周期,生命周期函数
生命周期函数代表的是Vue实例,或者是Vue组件,在网页中各个生命阶段所执行的函数。
- 创建实例对象:
1.beforeCreate创建实例对象之前执行
2.created创建实例对象之后执行
<script>
var vm=new Vue({
el:'#app',
data:{msg:'张三'},
beforeCreate(){
console.log('实例创建之前')
console.log('this.$data.msg')
},
created(){
console.log('实例创建之后')
console.log('this.$data.msg')
}
})
//beforeCreate钩子函数输出msg时出错,这是因为此时数据还没有被监听,同时页面没有挂载对象。而created钩子函数执行时,数据已经绑定到了对象实例,但是还没有挂载对象。
</script>
- 页面挂载
1.beforeMount页面挂载成功之前执行
2.mounted页面挂载成功之后执行
<script>
var vm=new Vue({
el:'#app',
data:{msg:'张三'},
beforeMount(){
console.log('挂载之前')
console.log('this.$el.innerHTML')
},
mounted(){
console.log('挂载之后')
console.log('this.$el.innerHTML')
}
})
//在挂载之前数据,数据并没有被关联到$el对象上,所以页面无法展示页面数据;在挂载之后,就获得了msg数据,并通过插值语法展示到页面中。
</script>
- 组件更新
1.beforeUpdate组件更新之前执行
2.updated组件更新之后执行
<script>
var vm=new Vue({
el:'#app',
data:{isShow:'false'},
beforeUpdate(){
console.log('更新之前')
console.log('this.$refs.self')
},
updated(){
console.log('更新之后')
console.log('this.$refs.self')
}
})
//通过点击实现挂载的更新
</script>
- 实例销毁
1.beforeDestroy实例销毁之前执行
2.destroyed实例销毁之后执行
<script>
var vm=new Vue({
el:'#app',
data:{msg:'张三'},
beforeDestroy(){
console.log('销毁之前')
console.log('this.$refs.self')
console.log(this.msg)
console.log(vm)
},
destroyed(){
console.log('销毁之后')
console.log('this.$refs.self')
console.log(this.msg)
console.log(vm)
}
})
//vm实例在beforeDestroy和destroyed函数执行时都存在,但是销毁之后获取不到页面中的div元素,所以实例销毁之后无法操作DOM元素。
</script>
28.Vue的数据双向绑定实现基本原理(MVVM模型)
Vue实现数据双向绑定主要采用数据劫持结合“发布-订阅”模式的方式,通过Object.defineProperty()的set和get,在数据变动时发布消息给订阅者触发监听。
个人理解的get函数里执行的任务就是watcher订阅者,而set函数执行的热恩物就是发布者。
Object.defineProperty()这个方法接受三个参数:属性所在对象,属性的名字,描述符对象。
29.watch
watch里绑定的是全局变量,当被绑定的全局变量发生改变时,Vue就自动触发watch里面对应的函数。
30.Vue渲染/更新流程
- 渲染流程:
1.解析模板为render函数
2.触发响应式,监听data属性getter setter
3.执行render函数,生成vnode,patch(elem,vnode) - 更新流程:
1.修改data,触发setter(此前在getter中已被监听)
2.重新执行render函数,生成newVnode
3.patch(vnode,newVnode)
31.webpack(模块打包器)模块化思想
模块化是指解决一个复杂问题时自上向下逐层把系统划分成若干模块的过程。
每一个模块完成一个特定的子功能,全部的模块按某种方式组装起来,成为一个总体,完成整个系统所要求的功能。
32.CSS盒模型
盒模型是CSS控制页面布局的一个非常重要的概念,页面上的所有元素,包括文本,图像,超级链接,div块等,都可以被看做盒子。
CSS的盒模型由里到外包括:content(内容),padding(内边距),border(边框),margin(外边距) 四部分。
内容content是盒子里的物品,是盒模型中必须有的部分,可以是网页上的任何元素,如文本,图片,视频等各种信息。
33.CSS中box-sizing
- box-sizing属性不能设在margin上。
- box-sizing是CSS里的属性,属性有content-box,border-box,默认值是content-box。
1.content-box:padding和border不被包含在定义的width和height之内。对象的实际宽度等于width+border+padding,表现为标准模式下的盒模型。
2.border-box:padding和border被包含在定义的width和height之内。对象的实际宽度就等于设置的width值,即使定义border和padding也不会改变对象的实际宽度,表现为怪异模式下的盒模型。
例子:
当创建宽度为100%,边框有10px的div时,div会溢出,此时就需要将box-sizing设置为border-box,就可解决。
34.布局position,flex
- position:定位属性。值有static(默认值)| relative(相对本身位置)| absolute(相对于离自身最近且position不为static的祖先元素,直到body)| fixed(相对于body元素)。
relative在布局层上占有位置(若让页面浮起来,它原来的位置还是被占用的)。
absolute和fixed在原先布局不占位置。 - flex:弹性布局。设置为flex布局以后,子元素的float,clear和vertical-align属性将失效。
1.flex-direction:决定主轴的方向,即排列顺序。
属性有:row(默认值,水平方向,起点在左端),row-reverse(水平方向,起点在右端),column(垂直方向,起点在上沿),column-reverse(垂直方向,起点在下沿)。
2.justify-content:定义了项目在主轴上的对齐方式。
属性有:flex-start(默认值,左对齐),flex-end(右对齐),center(居中),space-between(两端对齐,项目间的间隔相等),space-around(每个项目间隔相等)
3.align-items:定义项目在交叉轴上如何对齐。
属性有:flex-start(交叉轴的起点对齐),flex-end(交叉轴的终点对齐),center(交叉轴的中点对齐),baseline(项目的第一行文字的基线对齐),stretch(默认值,若项目未设置高度或设为auto,将占满整个容器的高度)
4.align-content:多根轴线的对齐方式。
属性有:flex-start(与交叉线的起点对齐),flex-end(与交叉线的终点对齐),center(与交叉线的中点对齐),space-between(与交叉线两端对齐,轴线之间的间隔平均),space-around(每根轴线两侧的间隔都相等),stretch(默认值,轴线占满整个屏幕)。
35.JS的二叉树先序遍历算法
先写出JS的对象形式
const tree = {
data: 1,
left: {
data: 2,
left: {
data: 4,
left: {
data: 8,
},
right: {
data: 9
}
},
right: {
data: 5,
left: {
data: 10,
},
right: {
data: 11
}
}
},
right: {
data: 3,
left: {
data: 6,
left: {
data: 12
}
},
right: {
data: 7
}
}
}
利用递归实现逻辑:
function binary(tree) {
//定义结果列表为空数组,存放数据
const output = [];
const list = (node) => {
if (node) {
// 先搜索出根节点的值,push进结果列表
output.push(node.data);
// 访问左子节点树,左子节点开始作为根节点进行下一轮递归
list(node.left);
// 同上述,递归遍历右子节点
list(node.right);
}
}
list(tree);
return output;
}
console.log('递归法DFS(先序): ', binary(tree));
// 递归法DFS(先序): [ 1, 2, 4, 8, 9, 5, 10, 11, 3, 6, 12, 7 ]
36.ES6的特性(let,const,模板字符串,箭头函数,解构,类等)
- 不一样的变量声明:const和let
let表示声明变量,而const表示声明常量,两者都为块级作用域,并且const声明的变量值设置完后就不能再修改了。
1.let允许创建块级作用域,不具备变量提升,不允许重复声明。
2.const允许创建块级作用域,变量声明不提升,const在声明时必须被赋值。 - 模板字符串
- 箭头函数
1.不需要function关键字来创建函数
2.省略return关键字
3.继承当前上下文的this关键字 - 函数的参数默认值
- 解构
- for…of和for…in
for…of用于遍历一个迭代器,如数组。
for…in用来遍历对象中的属性(只能访问可枚举的)。 - ES6中的类
ES6支持class语法,不过ES6的class不是新的对象继承模型,它只是原型链的语法糖表现形式。
37.promise
promise是异步编程的一种解决方案。
-
promise对象的特点:
1.对象的状态不受外界影响
promise对象代表一个异步操作,有三种状态:pending(进行中),fulfilled(已成功),rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
2.一旦状态改变,就不会再变,任何时候都可以得到这个结果
promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为resolved(已定型)。 -
promise的缺点:
1.无法取消promise,一旦新建它就会立即执行,无法中途取消。
2.如果不设置回调函数,promise内部抛出的错误,不会反应到外部。
3.当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
console.log("a");
setTimeout(()=>console.log("b"));
let p=new Promise((resolve,reject)=>{
resolve();
console.log("c");
}).then(()=>{
console.log("d");
});
console.log("e");
//输出结果依次为 a c e d b
- promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject:
1.resolve函数的作用是,将promise对象的状态从pending变为resolved。在异步操作成功时调用,并将异步操作的结果作为参数传递出去。
2.reject函数的作用是,将promise对象的状态从pending变为rejected。在异步操作失败时调用,并将异步操作报出的错误作为参数传递出去。 - then方法:
1.第一个回调函数是promise对象的状态变为resolved时调用。
2.第二个回调函数是promise对象的状态变为rejected时调用。
3.其中,第二个函数是可选的,不一定要提供。
4.这两个函数都接受promise对象传出的值作为参数。
promise.then(function(value){
//value
}, function(error){
//error
});
38.原型链
- 当对象原型是另一个构造函数的实例,如此迭代,形成了一连串的继承关系,即为原型链。
- 原型链表达了对象与对象之间的继承关系。
- 问题:
1.当原型链中包含引用值时,在各实例间共享的是该引用值的引用。
2.当某个实例修改该属性时,会影响全部实例。
3.子类型在实例化时不能个父类型传递参数。
39.利用迭代器和生成器写斐波那契数列
// 利用迭代器和生成器写斐波那契数列
class Fib {
constructor(num) {
this.num = num;
}
*[Symbol.iterator]() {
let [a, b] = [0, 1];
while (true) {
[a, b] = [b, a + b];
if (a > this.num) return;
yield a;
}
}
}
let fibs = new Fib(100);
for (let f of fibs) {
console.log(f);
}
40.symbol
- symbol类型,表示独一无二的值,是一个原始值,不能使用new命令
- symbol的值只能通过Symbol()函数生成
let s=Symbol();
console.log(typeof s);
- symbol函数可以接受一个字符串作为参数,表示对symbol实例的描述
let s1=Symbol('foo');
let s2=Symbol('bar');
console.log(s1,s1.toString());
console.log(s2,s2.toString());
- symbol的参数如果是一个对象,就会调用toString()方法,将其转换为字符串
const obj={
toString(){
return 'abc';
}
};
const sym=Symbol(obj);
console.log(sym);
- symbol函数的参数表示当前symbol值的描述,相同参数的symbol函数的返回值是不相等的
let sy1=Symbol();
let sy2=Symbol();
console.log('sy1==sy2',sy1==sy2);//false
let ssy1=Symbol('foo');
let ssy2=Symbol('foo');
console.log('ssy1==ssy2',ssy1==ssy2);
- Symbol.for和Symbol.keyFor同时出现
1.Symbol.for方法接受一个字符串,然后搜索有没有以该参数作为名称的Symbol值,有则返回,没有则进行创建。
2.Symbol.keyFor返回一个已登记的Symbol类型值的key。
let s1=Symbol('foo');
let s2=Symbol('foo');
console.log(s1==s2);//false
console.log(Symbol.keyFor(s1));//undefined
s1=Symbol.for('foo');
s2=Symbol.for('foo');
console.log(s1===s2);//true
console.log(Symbol.keyFor(s1));//foo