目录:
- 一、移动web
- 1.1 请说下初始化CSS样式的意义
- 1.2 谈谈你对HTML语义化的理解?
- 1.3 请说下如何居中一个div?
- 1.4 请说下px/em/rem这三个单位有什么区别?
- 1.5 你说下rem布局的原理和思路吧?
- 1.6 通过CSS如何写一个三角形?
- 1.7 如何实现两侧固定中间自适应的布局?
- 1.8 你知道BFC吗?
- 1.9、CSS选择器的优先级
- 1.10、HTML5新特性
- 1.11、CSS3新特性
- 1.12、CSS的盒子模型
- 1.13、移动端适配方案都有哪些
- 1.14、说出space-between和space-around的区别?(携程)
- 1.15、分析比较 opacity: 0、visibility: hidden、display: none优劣和适用场景?
- 1.16、 居中为什么要使用 transform(为什么不使用 margin-left/margin-top)(阿里)
- 1.17、介绍下粘性布局(sticky)(网易)
- 1.18、图片下方空白缝隙的解决方案
- 1.19、如何实现两栏布局
- 1.20、前端页面有哪三层构成,分别是什么?作用是什么?
- 二、JS基础
- 三、webapi
- 四、JS高级
- 五、ajax
一、移动web
- 面试要有条理性的回答:
- 多用以下词汇以利于事半功倍
- 原因…所以…最后
- 首先…其次…最后
1.1 请说下初始化CSS样式的意义
答:
1、浏览器差异:因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面显示差异。
2、提高编码质量:初始化CSS可以节约网页代码,节约网页下载时间;还会使得我们开发网页内容时更加方便简洁,不用考虑很多。如果不初始化,整个页面做完会很糟糕,重复的css样式很多。
常见写法:
①:最简单的初始化方法就是: * {padding: 0; margin: 0;}
。这样一个通用符在编写代码的时候是快,但这样写的话,他会把所有的标签都初始化一遍,这样就增加了网站运行的负载,会使网站加载过慢。
②:最好的做法是针对常用的标签进行初始化即可。
参考淘宝、腾讯等网站的css初始化:https://www.jb51.cc/css/1113842.html
1.2 谈谈你对HTML语义化的理解?
答:
根据页面的结构,选择合适的语义化标签,用正确的标签做正确的布局,同时有利于浏览器、搜索引擎的解析。
追问:为什么要语义化
1、HTML语义化让页面的内容结构化,结构更清晰,便于让浏览器、搜索引擎解析
2、即使在没有样式CSS情况下也以一种文档格式显示,并且是易于阅读的
3、搜索引擎也依赖于HTML标记来确定上下文和各个关键字的权重,利于SEO
4、使阅读源代码的人更容易将网站分块,便于阅读维护理解
追问:平时你写HTML代码还有那些注意事项?
1)尽可能少的使用无语义的标签div和span
2)在语义不明显时,既可以使用div或者p时,尽量用p,因为p在默认情况下有上下间距,对兼容特殊终端有利
3)不要使用纯样式标签,如:b、font、u等,改用CSS设置
4)需要强调的文本,可以包含在strong或者em标签中(浏览器预设样式,能用css指定就不用他们),strong默认样式是加粗(不要用b),em是斜体(不用i)
5)使用表格时,标题要用caption,表头用thead,主体部分用tbody包围,尾部用tfoot包围。表头和单元格要区分开,表头用th,单元格用td
6)表单域要用fieldset标签抱起来,并用legend标签说明表单的用途
7)每个input标签对应的说明文本都需要使用label标签,并且通过为input设置id属性,在label标签中设置for=someId来让说明文本和相对应的input关联起来
追问:你知道有哪些HTML5新增的语义标签?
article(定义文章)、aside(定义文章的侧边栏)、figure(一组媒体对象以及文字)、figurecaption(定义figure的标题)、footer(定义页脚)、header(定义页眉)、nav(定义导航栏)、section(定义文档中的区段)、time(定义日期和时间)、dialog(定义一个对话框)
1.3 请说下如何居中一个div?
答: 方法有很多,我大概记得以下5~6种吧。(回答可以直接说标题即可 如果非要说代码,也是说文字)
方法一: 利用定位
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.parent {
width: 500px;
height: 500px;
border: 1px solid #000;
position: relative;
}
.child {
width: 100px;
height: 100px;
border: 1px solid #999;
position: absolute;
top: 50%;
left: 50%;
margin-top: -50px;
margin-left: -50px;
}
</style>
</head>
<body>
<div class="parent">
<div class="child">我是子元素</div>
</div>
</body>
</html>
方法二:利用 margin:auto;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.parent {
width: 500px;
height: 500px;
border: 1px solid #000;
position: relative;
}
.child {
width: 100px;
height: 100px;
border: 1px solid #999;
position: absolute;
margin: auto;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
</style>
</head>
<body>
<div class="parent">
<div class="child">我是子元素</div>
</div>
</body>
</html>
方法三: 利用 display:table-cell
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.parent {
width: 500px;
height: 500px;
border: 1px solid #000;
display: table-cell;
vertical-align: middle;
text-align: center;
}
.c hild {
width: 100px;
height: 100px;
border: 1px solid #999;
display: inline-block;
}
</style>
</head>
<body>
<div class="parent">
<div class="child">我是子元素</div>
</div>
</body>
</html>
方法四: 利用 display: flex;设置垂直水平都居中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.parent {
width: 500px;
height: 500px;
border: 1px solid #000;
display: flex;
justify-content: center;
align-items: center;
}
.c hild {
width: 100px;
height: 100px;
border: 1px solid #999;
}
</style>
</head>
<body>
<div class="parent">
<div class="child">我是子元素</div>
</div>
</body>
</html>
方法五: 计算父盒子与子盒子的空间距离(这跟方法一是一个道理) (不够好:自己算)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.parent {
width: 500px;
height: 500px;
border: 1px solid #000;
}
.c hild {
width: 100px;
height: 100px;
border: 1px solid #999;
margin-top: 200px;
margin-left: 200px;
}
</style>
</head>
<body>
<div class="parent">
<div class="child">我是子元素</div>
</div>
</body>
</html>
方法六: 利用 transform
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.parent {
width: 500px;
height: 500px;
border: 1px solid #000;
position: relative;
}
.c hild {
width: 100px;
height: 100px;
border: 1px solid #999;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
<div class="parent">
<div class="child">我是子元素</div>
</div>
</body>
</html>
1.4 请说下px/em/rem这三个单位有什么区别?
答:
①: px 是绝对单位,而 em 和 rem 是相对单位。
②: em相对于当前元素内文本的字体大小,找不到就找父亲的文字大小,而 rem是相对的HTML 根元素文字大小
③: px适合于固定文字大小, em经常用于比如段落首行缩进等, rem在后期移动端开发经常用于做适配。
1.5 你说下rem布局的原理和思路吧?
答:
1、rem 是css的相对单位,rem缩放是相对根元素字体大小.
2、rem 布局的本质是等比缩放,一般是基于宽度。
3、rem 会配合媒体查询(或js动态获取屏幕宽度)来一起使用,来实现屏幕的适配。
rem布局实现目的: 等比缩放
1、元素所有属性 只要px单位—>rem单位
2、rem单位非常神奇,背后 基准值会变。
3、基准值取决于根元素字号大小,屏幕变化导致根元素字号大小变;
4、实现原理:给window注册resize。当变化内部函数设置 根元素字号大小 = 为当前屏幕宽度 / 固定数值 通常为10
1.6 通过CSS如何写一个三角形?
答:
利用css边框属性就可以得到三角形。
边框是梯形的,如果盒子没有宽高,则会变成三角形,设置三个角透明色,其中一个角给颜色,就能得到三角形了
1.7 如何实现两侧固定中间自适应的布局?
答:
圣杯布局
最简单方法,可以通过flex布局来显示, 大盒子里面包含左中右三个小盒子,父盒子利用display:flex。两侧直接写固定宽度,中间盒子给flex:1 即可。
传统方案:父亲设置 box-sizing:border-box CSS3盒子模型,设置左右padding, 子元素三个:左右侧绝对定位宽度(正好是设置padding)高度同父亲 。 中间:设置100%宽 100%高
1.8 你知道BFC吗?
答:
①:BFC(Block Formatting Context),即块级格式化上下文,它是页面中的一块渲染区域,并且有一套属于自己的渲染规则,BFC目的是形成一个相对于外界完全独立的空间,让内部的子元素不会影响到外部的元素
②:触发BFC的条件
- 根元素,即HTML元素
- 浮动元素:float值为left、right
- overflow值不为 visible,为 auto、scroll、hidden
- display的值为inline-block、inltable-cell、table-caption、table、inline-table、flex、inline-flex、grid、inline-grid
- position的值为absolute或fixed
③:BFC的主要使用场景:
- 防止margin重叠(塌陷)。 比如给父级添加overflow,就触发了BFC, 还有子元素浮动,不会触发外边距塌陷原因也是因为触发了BFC
- 清除内部浮动。 同样,清除浮动方法中有个overflow:hidden 方法
1.9、CSS选择器的优先级
!important > 行内样式>ID选择器 > 类选择器 > 标签 > 通配符 > 继承
1.10、HTML5新特性
1. 语义化标签: header nav section article aside footer
2. 多媒体标签: video audio
3. input类型: number search email tel date file time url
4. 本地离线存储 localStorage 长期存储数据,改变浏览器数据不会丢失
sessionStorage 浏览器关闭数据会丢失
5. 自定义属性 data-*
6. 画布 Canvas
7. webscoket 双向通信协议
1.11、CSS3新特性
1. 圆角 border-radius
2. 盒子模型 box-sizing
3. 阴影 box-shadow 盒子阴影 text-shadow 文字阴影
4. 过渡 transition
5. 2D转换transform translate(平移) scale(缩放) skew(斜切) rotate(旋转) transform-origin 控制转换中心点
6. 3D转换 perspective(透视距) transform-style(3D控件效果)
7. 渐变 linear-gradient radial-gradient
8. 弹性布局 flex
9. 媒体查询 @media screen and () {...}
10. 边框图片 border-image
11. 自定义动画 @keyframes animation
12. 颜色 新增RGBA HSLA模式
13. 背景 background-size background-origin background-clip
1.12、CSS的盒子模型
1、有两种, IE 盒子模型、标准盒模型;
2、IE盒模型设置的宽为:整个盒子所占有的宽度。(内容的宽+左右padding+左右border)
3、标准盒模型就是内容区域的宽。
可以通过box-sizing 属性来设置他们:
● content-box 是默认值。盒子的实际大小为:content + padding + border 相加后的值
● border-box:设置的边框和内边距的值是包含在 width 内的。也就是说,如果你将一个元素的
width 设为 100px,那么这 100px 会包含它的 border 和 padding,内容区的实际宽度是
width 减去 (border + padding) 的值。
1.13、移动端适配方案都有哪些
1. 响应式布局: Bootstrap,腾讯全端等网站采用这个方法:
主要是利用媒体查询,根据不同的页面宽度进行不同的样式设置
2. rem + flexible.js: 手机淘宝团队采用这个方法
rem单位回根据html的font-size大小进行转变的单位 1rem = html的font-size大小
flexible.js 能够动态的获取当前设备视口宽度,给html标签设置font-size,因此能够实现移动适配
3. vw / vmin :哔哩哔哩
vw是一个视口单位,是指相对于视口的宽度;视口会被均分为100份,其中1vw等于视口宽度的1%,
比如浏览器的宽度为1920px,则“1vw=1920px/100=19.2px”。
该方案解决了rem 需要依赖不同html的font-size尺寸的问题,他相对于当前设备的视口宽高来进行变化。
- vw:相对于视口的宽度, 视口被均分为 100 单位的vw,1vw等于视口宽度的1%。
- vh: 相对于视口的宽度, 视口被均分为 100 单位的vh,1vh等于视口高度的1%。
- vmin:选取vw和vh中最小的那个。
- vmax:选取vw和vh中最大的那个。
4. flex布局:天猫的实现方式进行说明:
利用弹性盒子的特点宽度自适应,高度定死,元素采用px做单位。随着屏幕宽度宽度发生变化,
页面也会跟着变化,这里因为高度是不会随着设备的变化发生改变的,所以并不是完整的移动端适配,
效果就和PC页面的流式布局差不多
1.14、说出space-between和space-around的区别?(携程)
这个是 flex 布局的内容,其实就是一个边距的区别,按水平布局来说,
space-between是两端对齐,在左右两侧没有边距,而space-around是每个
子项目左右方向的 margin 相等,所以两个item中间的间距会比较大。
1.15、分析比较 opacity: 0、visibility: hidden、display: none优劣和适用场景?
display: none (不占空间,不能点击)(场景,显示出原来这里不存在的结构)
visibility: hidden(占据空间,不能点击)(场景:显示不会导致页面结构发生变动,不会撑开)
opacity: 0(占据空间,可以点击)(场景:可以跟transition搭配)
1.16、 居中为什么要使用 transform(为什么不使用 margin-left/margin-top)(阿里)
transform 属于合成属性(composite property),对合成属性进行 transition/animation
动画将会创建一个合成层(composite layer),这使得被动画元素在一个独立的层中进行动画。
通常情况下,浏览器会将一个层的内容先绘制进一个位图中,然后再作为纹理(texture)上传到
GPU,只要该层的内容不发生改变,就没必要进行重绘(repaint),浏览器会通过重新复合
(recomposite)来形成一个新的帧。
margin-top/margin-left属于布局属性,该属性的变化会导致重排(reflow/relayout),
所谓重排即指对这些节点以及受这些节点影响的其它节点,进行CSS计算->布局->重绘过程,
浏览器需要为整个层进行重绘并重新上传到 GPU,造成了极大的性能开销。
1.17、介绍下粘性布局(sticky)(网易)
position 中的 sticky 值是 CSS3 新增的,设置了 sticky 值后,在屏幕范围(viewport)
时该元素的位置并不受到定位影响(设置是top、left等属性无效),当该元素的位置将要移出
偏移范围时,定位又会变成fixed,根据设置的left、top等属性成固定位置的效果。
sticky 属性值有以下几个特点:
该元素并不脱离文档流,仍然保留元素原本在文档流中的位置。
当元素在容器中被滚动超过指定的偏移值时,元素在容器内固定在指定位置。亦即如果你
设置了top: 50px,那么在sticky元素到达距离相对定位的元素顶部50px的位置时固定,
不再向上移动。
元素固定的相对偏移是相对于离它最近的具有滚动框的祖先元素,如果祖先元素都不可以滚动,
那么是相对于viewport来计算元素的偏移量
1.18、图片下方空白缝隙的解决方案
产生空白缝隙原因:因为行内和行内块对齐方式问题,图片默认和文字的基线对齐,所以会出现底部缝隙。
解决方法:
1. 修改图片显示模式,除行内和行内块显示模式
2. 给图片设置vertical-align: 除baseline以外的值
3. 设置父元素文字大小为 0
1.19、如何实现两栏布局
1. 利用margin和浮动
左侧盒子左浮动,浮动后脱标,右侧盒子设置margin-left,值就是左侧盒子的宽度
2. 利用flex布局
父级开启flex布局,左侧盒子设置固定宽度,右侧盒子可以设置flex:1;
3. 利用绝对定位
利用绝对定位,将父级元素设置为相对定位。
左边元素设置为absolute定位,并且固定宽度设置为200px,left值设置为0。
将右边元素的left值设置为左边固定宽度200px,right值设置为0
1.20、前端页面有哪三层构成,分别是什么?作用是什么?
web标准有三部分组成:结构html、表示css、行为 javascript
1、结构层:由 HTML 标记语言负责创建,仅负责语义的表达。解决了页面“内容是什么”的问题。
2、表示层:由CSS负责创建,解决了页面“如何显示内容”的问题。
3、行为层:由脚本(js)负责。解决了页面上“内容应该如何对事件作出反应”的问题
二、JS基础
2.1 说下typeof返回的数据类型
回答:
①:简单数据类型直接返回对应的英文,比如:number string boolean undefined 等,特殊情况,null 返回 object
②:复杂数据类型返回 object,函数返回的是 function fn(){…} typeof fn
2.2 请说下转换为false的情况有哪些?
答:
七种
自动转换为false的有: 0 、 “”、 null、 false、 NaN、 undefined、还有不成立的表达式
2.3 两个等号和三个等号的区别是什么?
回答:
== 表示是相等,只比较内容,类型不同,会隐式转换为同类型,进行比较。
=== 表示是全等,不仅比较内容,也比较类型。如果类型不同,直接false
2.4 请说说你对作用域链的理解?
回答:
①:JavaScript中的作用域分为全局作用域、局部作用域,多个嵌套的作用域形成作用域链。
②:作用域链:内部寻找一个变量的查找规则,
- 规则:
- 当在某个作用域中查找变量时,如果当前作用域没有找到,则向上层作用域查找,上层没有声明,继续向上层查找,一直找到全局作用域。
- 找的过程中,找到则使用该变量,没有找到则报错。
2.5 简单数据类型与复杂数据类型在内存上存储有什么区别?
回答:
①:基本类型(简单类型)主要为以下6种:Number、String、Boolean、Undefined、null、symbol
- 基本数据类型的值存储在 栈中
②:引用类型(复杂类型) Object、Array、Function
- 引用类型的值存储于 堆中
三、webapi
3.1 请说下什么是重绘和重排(回流)?他们的区别是什么?
回答:
重排: 也叫做回流,当DOM元素影响了元素的几何属性(例如宽和高),浏览器需要重新计算元素的几何属性,同样其它元素的几何属性和位置也会因此受到影响。浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。这个过程称为“重排”。
重绘: 完成重排后,浏览器会重新绘制受影响的部分到屏幕上中,该过程称为“重绘”。
总结:
当我们改变DOM的大小,增加删除都会导致重排,当给DOM元素改变颜色的时候,会导致重绘,重排一定会重绘,重绘不会重排。重排会影响性能,所以我们尽快能的减少重排的操作(这句话是重点)
追问:
1问:那么如何触发重排和重绘?
任何改变用来构建渲染树的信息都会导致一次重排或重绘:
添加、删除、更新DOM节点
通过display: none隐藏一个DOM节点-触发重排和重绘
通过visibility: hidden隐藏一个DOM节点-只触发重绘,因为没有几何变化
移动或者给页面中的DOM节点添加动画
添加一个样式表,调整样式属性
用户行为,例如调整窗口大小,改变字号,或者滚动。
2问:重绘与重排的区别?
重排: 部分渲染树(或者整个渲染树)需要重新分析并且节点尺寸需要重新计算,表现为重新生成布局,重新排列元素
重绘: 由于节点的几何属性发生改变或者由于样式发生改变,例如改变元素背景色时,屏幕上的部分内容需要更新,表现为某些元素的外观被改变
单单改变元素的外观,肯定不会引起网页重新生成布局,但当浏览器完成重排之后,将会重新绘制受到此次重排影响的部分
重排和重绘代价是高昂的,它们会破坏用户体验,并且让UI展示非常迟缓,而相比之下重排的性能影响更大,在两者无法避免的情况下,一般我们宁可选择代价更小的重绘。
『重绘』不一定会出现『重排』,『重排』必然会出现『重绘』。
3.2 说说this的指向问题吧?
回答: 谁调用执行谁。
this是个关键字,它的指向和函数的调用方式有关, 初步的理解就是,this指向所在函数的调用者。
1、 以函数形式调用时, this 永远都是 window
2、 以方法的形式调用时, this 是调用方法的对象
let obj = {
fn:function(){
log(this)
}
}
obj.fn(); // this--->obj
3、 以构造函数的形式调用时, this 是新创建的那个对象
4、 使用 call 和 apply 调用时, this 是指定的那个对象
5、 箭头函数: 箭头函数的 this 按照普通变量对待。比如把他当做 x 变量即可,然后按照作用域链找就行了。
6、全局中的this是window
7、事件处理函数,如果是普通的function函数,则this指向事件源。
3.3 事件流分为哪两个阶段?
事件流是指事件传播的顺序,由事件捕获 => 目标事件 => 事件冒泡
所以事件流分为捕获和冒泡两个阶段。
3.4 事件委托的实现原理?如果获取当前触发的dom节点?
回答:
①:事件委托主要利用事件冒泡特性来实现的。
②:事件委托(事件委派)主要有2个使用场景:
- 如果有多个子元素,可以把事件注册给父元素,因为点击子元素,也会将事件冒泡到其父元素上,利用这个特点提高了性能。
- 给后来动态生成的元素绑定事件。因为动态生成的元素没有办法直接绑定事件,可以利用事件委托来绑定事件。
使用 e.target 获取当前触发事件的元素。
3.5 你能说说怎么理解事件循环机制的?
回答:
1、JavaScript 是一门单线程语言. 单线程可能会出现阻塞的情况,所js分了同步任务和异步任务。
2、同步和异步任务分别进入不同的执行环境,同步的进入主线程,即主执行栈,异步的进入 任务队列。
3、主线程内的任务执行完毕为空,会去 任务队列 读取对应的任务,推入主线程执行。 上述过程的不断重复就是我们说的 Event Loop (事件循环)。
四、JS高级
4.1、什么是深/浅拷贝
浅拷贝: 拷贝对象的一层属性,如果对象里面还有对象,拷贝的是地址, 两者之间修改会有影响,适用于对象里面属性的值是简单数据类型的.
深拷贝: 拷贝对象的多层属性,如果对象里面还有对象,会继续拷贝,使用递归去实现.
4.2、如何用递归实现深拷贝?
function copy(oldD) {
let newD // 新数据
// 需要判断oldD 何方数据类型?
// ************************************数组
if(oldD instanceof Array){
newD = []
for (let i = 0; i < oldD.length; i++) {
let val = oldD[i] // 每一项数据
val = copy(val) // val
newD.push(val)
}
}
// ***********************************对象
else if(oldD instanceof Object){
newD = {}
for (let key in oldD) {
let val = oldD[key] // 每一项数据,有可能又是简单数组
val = copy(val) // val不能直接赋值,需要经过copy
newD[key] = val // 添加键值对
}
}
// ***********************************简单数据
else {
newD = oldD
}
return newD
}
其他方式:
lodash:_.cloneDeep(被拷贝的对象)
JSON.parse(JSON.stringify(被拷贝的对象))
4.3、描述下垃圾回收机制?
首先:垃圾回收机制内部算法:引用计数 和 标记清除
接下来:
● 引用计数:把堆上对象能够访问次数记下来,如果发现某个对象计数为0,算法认为没有变量访问这个对象。该对象所占空间,判定是垃圾,进行回收。但是:如果两个对象相互引用,各自计数永远不会为0,不会判定为是垃圾,不会回收。所以:主流浏览器不再使用该算法。
● 标记清除:核心就是 从 使用对象次数 到 无法到达对象;只要是堆上对象无法访问,哪怕是对象相互引用,但是无法访问,算法对该对象标记为垃圾空间。
4.4、对闭包是怎么理解的?
答:
● 基本形式:两个嵌套关系的函数,内部函数可以访问外部函数定义的局部变量,那么该变量与内部函数就构造了闭包的形式
● 优点:形成私有空间,避免全局变量的污染
● 缺点:持久化内存,导致内存泄露
● 解决:
○ 1、尽快避免函数的嵌套,以及变量的引用
○ 2、执行完的变量,可以赋值null,触发垃圾回收机制,进行回收释放内存
4.5、什么是原型对象和原型链
答:
原型对象:每个构造函数都有prototype属性,这个属性的值是个对象,称之为原型对象。
原型链:对象都有__proto__属性,这个属性指向它的原型对象,原型对象也是对象,也有__proto__属性,指向原型对象的原型对象,这样一层一层形成的链式结构称为原型链.
4.6、原型链有什么意义?
总得来说:给实例化对象上调用方法或使用某个属性,提供查询机制。
具体查询:
先在实例化对象本身上去找该方法。
如果没有,去实例化对象的__proto__(原型对象上去找)
如果当前原型对象上还没有该方法,继续往原型对象上的原型对象上去找
如果还是没有找到,报错 对象.xxx is not function
4.7、call、apply和bind的区别
答:
1、call和apply方法都可以调用函数,方法内的第一个参数可以修改this的指向
2、call方法可以有多个参数,除了第一个参数,其他参数作为实参传递给函数;apply方法最多有2个参数,第二个参数是个数组或伪数组,数组里面的每一项作为实参传递给函数
3. bind方法不能调用函数,它会创建一个副本函数,并且该新函数的this指向已经被改变。
4.8、怎么理解函数的防抖和节流
防抖:就是指触发事件后,在n秒后对应的函数会执行。如果在n秒中又触发了事件,则会重新计算函数执行时间。
节流:就是指连续触发事件,如果上一次触发的对应的执行函数没有执行完成,下一次触发是不会引起对应代码执行的
4.9、关键字new的执行过程?
1、在函数内部创建空对象{}
2、this变量 此时本次调用中 代表当前对象
3、this.属性名 相当于往 对象 添加属性名
4、随着调用传入实参,实参添加到对应属性名上属性值
5、把对象return出来
五、ajax
5.1、请说出宏任务与微任务,在事件循环机制中是如何执行的?
答:
1、代码:分为【宏任务】与【微任务代码】
【宏任务】:主代码块、定时器代码、dom节点事件触发代码、ajax代码 ;(主代码块: script标签包着这些代码)
【微任务】 promise实例对象的.then(回调函数)
2、宏任务与微任务都会去【宿主环境】。
3、这些代码里面回调函数到了要执行点的时候,不是直接去【主线程】,而是去【任务队列】。到了【任务队列】分为两个队列【宏任务队列】与【微任务队列】
4、最一开始【事件循环机制】先执行 【主代码块】,又会分为:
异步代码:在执行的过程中又分出来【宏任务】与【微任务】到【宿主环境】,然后各自排队到任务队列里的【宏任务队列】与【微任务队列】
同步代码:分到主线程上,就继续执行。
5、执行完第一个主代码里面同步代码后,【事件循环机制】会先把【微任务队列】里面所有函数执行完成后,才去执行【宏任务队列】的下一个的函数。
简叙:任务队列里执行函数【微任务队列】比【宏任务队列】优先。
例题:(答案博主就不发了,可以通过运行代码知道答案,或者私聊博主)
例题1:
<script>
console.log(1);
setTimeout(() => {
console.log(2);
}, 0)
console.log(3);
</script>
<script>
console.log(4);
setTimeout(() => {
console.log(5);
}, 0)
console.log(6);
</script>
例题2:
console.log(1)
setTimeout(function() {
console.log(2)
}, 0)
const p = new Promise((resolve, reject) => {
console.log(3)
resolve(1000) // 标记为成功
console.log(4)
})
p.then(data => {
console.log(data)
})
console.log(5)
例题三:
new Promise((resolve, reject) => {
resolve(1)
new Promise((resolve, reject) => {
resolve(2)
}).then(data => {
console.log(data)
})
}).then(data => {
console.log(data)
})
console.log(3)
例题四:
setTimeout(() => {
console.log(1)
}, 0)
new Promise((resolve, reject) => {
console.log(2)
resolve('p1')
new Promise((resolve, reject) => {
console.log(3)
setTimeout(() => {
resolve('setTimeout2')
console.log(4)
}, 0)
resolve('p2')
}).then(data => {
console.log(data)
})
setTimeout(() => {
resolve('setTimeout1')
console.log(5)
}, 0)
}).then(data => {
console.log(data)
})
console.log(6)
例题五:
<script>
console.log(1);
async function fnOne() {
console.log(2);
await fnTwo(); // 右结合先执行右侧的代码, 然后等待
console.log(3);
}
async function fnTwo() {
console.log(4);
}
fnOne();
setTimeout(() => {
console.log(5);
}, 2000);
let p = new Promise((resolve, reject) => { // new Promise()里的函数体会马上执行所有代码
console.log(6);
resolve();
console.log(7);
})
setTimeout(() => {
console.log(8)
}, 0)
p.then(() => {
console.log(9);
})
console.log(10);
</script>
<script>
console.log(11);
setTimeout(() => {
console.log(12);
let p = new Promise((resolve) => {
resolve(13);
})
p.then(res => {
console.log(res);
})
console.log(15);
}, 0)
console.log(14);
</script>
例题六:
<script>
console.log(1);
async function fnOne() {
console.log(2);
await fnTwo(); // 右结合先执行右侧的代码, 然后等待
console.log(3);
}
async function fnTwo() {
console.log(4);
}
fnOne();
setTimeout(() => {
console.log(5);
}, 2000);
let p = new Promise((resolve, reject) => { // new Promise()里的函数体会马上执行所有代码
console.log(6);
resolve();
console.log(7);
})
setTimeout(() => {
console.log(8)
}, 0)
p.then(() => {
console.log(9);
})
console.log(10);
</script>
<script>
console.log(11);
setTimeout(() => {
console.log(12);
let p = new Promise((resolve) => {
resolve(13);
})
p.then(res => {
console.log(res);
})
console.log(15);
}, 0)
console.log(14);
</script>
5.2、http和https的区别
答:
1.https协议需要到CA申请证书,一般免费证书较少,因而需要一定费用。
2.http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl/tls加密传输协议。
3.http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4.http的连接很简单,是无状态的;HTTPS协议是由SSL/TLS+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
5.3、get 和post的区别
答:
get
- 在url后面拼接参数,只能以文本的形式传递数据
- 传递的数据量小,4KB左右
- 安全性低, 会将数据显示在地址栏
- 速度快,通常用于安全性要求不高的请求
- 会缓存数据
post
- 安全性比较高
- 传递数据量大,请求对数据长度没有要求
- 请求不会被缓存,也不会保留在浏览器历史记录里
5.4、在地址栏输入网址,到数据返回的过程是什么?
- 输入url地址后,首先进行DNS解析,将相应的域名解析为IP地址。
- 根据IP地址去寻找相应的服务器。
- 与服务器进行TCP的三次握手,建立连接。
- 客户端发送请求,找到相应的资源库。
- 客户端拿到数据,进行相应的渲染。
5.5、怎么理解三次握手
答:
第一次握手:建立连接时,客户端发送syn包到服务器,等待服务器确认。
第二次握手:服务器收到syn包,必须确认客户的SYN,同时自己也发送一个SYN包(syn=y)到客户端
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK,此包发送完毕,客户端和服务器进入(TCP连接成功)状态,完成三次握手
通俗:
第一次:客户端告诉服务器,我有个诉求,想要向你请求数据,你能听见么?
第二次:服务器告诉客户端,收到你的诉求,允许请求数据,你能听见么?
第三次:客户端告诉服务器,OK收到。
6、怎么理解四次挥手
答:
第一次分手:客户端向服务器发送一个FIN报文段;此时,客户端进入FIN_WAIT_1状态;这表示没有数据要发送给服务器了。
第二次分手:服务器 收到 客户端 发送的FIN报文段,向 客户端 回一个ACK报文段,主机1进入FIN_WAIT_2状态;服务器告诉 客户端,我知道你的诉求了,也“同意”你的关闭请求,但是具体什么时候关闭,等我通知;
第三次分手:服务器 向 客户端 发送FIN报文段,说可以正式关闭连接了,同时 服务器 进入LAST_ACK状态。
第四次分手:客户端 收到 服务器 发送的FIN报文段,向 服务器 发送ACK报文段,然后 客户端 进入TIME_WAIT状态;服务器 收到 客户端的ACK报文段以后,服务器就正式关闭连接;此时,客户端等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,客户端也可以正式关闭连接了。
通俗:
第一次分手:客户端告诉服务器,我有个诉求,我这边没有数据了,我要准备关闭了。
第二次分手:服务器收到信息后,回复:我收到你的诉求了,你可以进行准备着,但是何时正式关闭,等我通知。
第三次分手:服务器 给 客户端发信:你现在准备正式关闭了。
第四次分手:客户端 给 服务器发信:OK呢,我知道了。
(服务器:收到信息后,服务器正式关闭了)
(客户端:???等了一会,这家伙没有说就下线了,嗯~真的关了,好吧,我也是正式关了。)
(持续更新中~~,家人们关注博主不迷路,向创作优质内容而努力,注:以上全是自己的整理,如有错误请联系博主)