参考文档后边会补上
CSS+HTML
HTML5新增了哪些新的属性?
新增语义结构标签
新增表单元素
新增表单属性 form 和 input
HTML5语义化标签的理解,了不了解可访问性
html语义化就是让页面的内容结构化,便于对浏览器、搜索引擎解析;
在没有样式CSS情况下也以一种文档格式显示,并且是容易阅读的。
搜索引擎的爬虫依赖于标记来确定上下文和各个关键字的权重,利于 SEO。
使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解
提升代码可读性,便于团队开发和维护,当网页去掉CSS样式时,页面能呈现出来清晰的结构
Doctype作用?严格模式混杂模式如何区分?有何意义?
<!DOCTYPE> :
1、声明位于文档中的最前面,处于 <html> 标签之前。HTML5中不区分大小写
2、<!DOCTYPE>声明不是HTML标签,是一个告知浏览器的解析器, 【用什么文档类型】规范来解析这个文档的指令
在混杂模式中,页面以宽松的向后兼容的方式显示。模拟老式浏览器的行为以防止站点无法工作。 DOCTYPE不存在或格式不正确会导致文档以混杂模式呈现
块级元素和行内元素(内联元素)区别 ♥
1.行内元素:
和其他行内元素都会在一条水平线上排列,都是在同一行的;
不能设置width和height;宽高随文本内容的变化而变化,可设置行高,同时在设置外边距margin上下无效,左右有效,内填充padding上下无效,左右有效;
【只可以设置水平方向(左右)的边距,如:margin-left,margin-right,padding-left,padding-right.】
块级元素:
各个块级元素独占一行,垂直向下排列,若想使其水平方向排序,可使用左右浮动(float:left/right)让其水平方向排列。
可以设置宽高,默认宽度为父级的100%,宽度高度以及外边距,内填充都可随意控制。
2.相互转换:
通过修改display属性值来切换块级元素和行内元素,display:inline(变为行内元素), display:block(转为块级元素)。
float浮动。
注意:display:inline-block;行内块 缺点:间隙、基线对齐问题
float 浮动 行内块 缺点:脱离文档流(父级找不到子级) 优点:没有基线对齐问题、间隙
3.块级元素可以包含行内元素和块级元素,还可以容纳内联元素和其他元素;行内元素不能包含块级元素,只能容纳文本或者其他行内元素。
♥ ♥ ♥ img元素属于块级元素还是行内元素?
img标签没有独占一行,是行内元素,属于替换元素,具有内置的宽高属性,所以可以设置宽高
空元素: <br> <hr> <img> <input> <link> <meta>
水平居中,垂直居中 ♥ ♥ ♥
-
水平居中
1、行内元素:看父元素是不是块级元素,是,则直接给父元素设置text-align: center; 不是,则先将父元素设置为块级元素,再给父元素设置text-align: center; 2、块级元素: 1)分宽度定不定两种情况: 定宽度:需要谁居中,给其设置margin: 0 auto;(作用:使盒子自己居中); 不定宽度:默认子元素的宽度和父元素一样,这时需要设置子元素为display: inline-block;或 display: inline;即将其转换成行内块级/行内元素,给父元素设置 text-align: center; 2)使用定位 首先设置父元素为相对定位,再设置子元素为绝对定位,设置子元素的left:50%,即让子元素的左上角水平居中; 定宽度:设置绝对子元素的margin-left: -元素宽度的一半px; 或者设置transform: translateX(-50%); 不定宽度:利用css3新增属性transform: translateX(-50%); 3)使用flexbox布局(宽度定不定都可以) 使用flexbox布局,只需要给待处理的块状元素的父元素添加属性 display: flex; justify-content: center; -
垂直居中
1、单行的行内元素 只需要设置单行行内元素的"行高等于盒子的高"即可line-height; 2、多行的行内元素 使用给父元素设置display:table-cell;和vertical-align: middle;属即可; 3、块级元素 1)使用定位 首先设置父元素为相对定位,再设置子元素为绝对定位,设置子元素的top: 50%,即让子元素的左上角垂直居中; 定高度:设置绝对子元素的 margin-top: -元素高度的一半px; 或者设置transform: translateY(-50%); 不定高度:利用css3新增属性transform: translateY(-50%); 2)使用flex布局实现(高度定不定都可以) 使用flex布局,只需要给待处理的块状元素的父元素添加属性 display: flex; align-items: center; -
水平垂直居中
1、已知高度和宽度的元素 1)设置父元素为相对定位,给子元素设置绝对定位,top: 0; right: 0; bottom: 0; left: 0; margin: auto; 2)设置父元素为相对定位,给子元素设置绝对定位,left: 50%; top: 50%; margin-left: -元素宽度的一半px; margin-top: -元素高度的一半px; 2、未知高度和宽度的元素 1)使用定位 设置父元素为相对定位,给子元素设置绝对定位,left: 50%; top: 50%; transform: translateX(-50%) translateY(-50%); 2)使用flex布局 设置父元素为flex定位,justify-content: center; align-items: center;
鼠标移动到元素上,改变宽高的方法
scale 和直接改变宽高哪个方式更好
CSS中transform的scale(x, y)方法动态调整视频宽高大小实现满屏播放
回流(重排)、重绘,哪个更消耗性能及其运用 ,如何减少 ♥ ♥ ♥ ♥
回流:当渲染树中的一部分(或全部)因为元素的尺寸、布局、隐藏等改变而重新构建。每个页面至少需要一次回流,就是页面在第一次加载的时候
重绘:当渲染树中的一些元素需要更新属性,而这些属性只是影响元素的外观、风格,而不会影响布局的。
注意:回流必将引起重绘,而重绘不一定会引起回流
回流更消耗性能,回流的花销跟渲染树有多少节点需要重新构建有关系
如何减少:
合并多次对DOM和样式的修改,然后一次处理掉
触发回流的条件:任何页面布局和几何属性的改变都会触发重排:
页面渲染初始化(无法避免)
添加或删除可见的DOM元素
元素位置的改变,或者使用动画
元素尺寸的改变——大小,外边距,边框
浏览器窗口尺寸的变化
填充内容的改变,比如文本的改变或图片大小改变而引起的计算值宽度和高度的改变
针对重绘回流的优化方案
1、元素位置移动变换时尽量使用CSS3的transform来代替top,left等操作
2、不要使用table布局
3、将多次改变样式属性的操作合并成一次操作
4、利用文档素碎片(documentFragment),vue使用了该方式提升性能
5、动画实现过程中,启用GPU硬件加速:transform:tranlateZ(0)
6、为动画元素新建图层,提高动画元素的z-index
7、编写动画时,尽量使用requestAnimationFrame
transform 不重绘,不回流
是因为transform属于合成属性,对合成属性进行transition/animate动画时,将会创建一个合成层。这使得动画元素在一个独立的层中进行渲染。当元素的内容没有发生改变,就没有必要进行重绘。浏览器会通过重新复合来创建动画帧。
浏览器渲染的先后次序,过程 ♥ ♥ ♥ ♥
1、渲染引擎解析HTML文档,生成DOM树,解析CSS,生成CSSOM树 (将html代码按照深度优先遍历来生成DOM树。)
2、将DOM树和CSSOM树结合,生成渲染树(Render Tree)
为了构建渲染树,浏览器主要完成了以下工作:
从DOM树的根节点开始遍历每个可见节点。
对于每个可见的节点,找到CSSOM树中对应的规则,并应用它们。
根据每个可见节点以及其对应的样式,组合生成渲染树。
第一步中,既然说到了要遍历可见的节点,那么我们得先知道,什么节点是不可见的。不可见的节点包括:
一些不会渲染输出的节点,比如script、meta、link等。
一些通过css进行隐藏的节点。比如display:none。注意,利用visibility和opacity隐藏的节点,还是会显示在渲染树上的。只有display:none的节点才不会显示在渲染树上。
注意:渲染树只包含可见的节点
3、Layout(回流):根据生成的渲染树,进行回流(Layout),得到节点的几何信息(位置,大小)
4、Painting(重绘):根据渲染树以及回流得到的几何信息,得到节点的绝对像素
5、Display:将像素发送给GPU,展示在页面上。
1、浏览器会从上到下解析文档
2、遇见HTML标记,调用HTML解析器解析为对应的token(一个token就是一个标签文本的序列化)并构建DOM树(就是一块内存,保存着tokens,建立他们之间的关系)
3、遇见style/link标记调用相应解析器处理CSS标记,并构建出CSS样式树
4、遇见script标记,调用JavaScript引擎处理script标记,绑定事件,修改DOM树/CSS树等
5、将DOM树与CSS合并成一个渲染树
6、根据渲染树来渲染,以计算每个节点的几何信息(这一过程需要依赖GPU)
7、最终将各个节点绘制在屏幕上
html ,css 和js对页面渲染性能的影响
浏览器渲染时可以加载css吗?渲染和下载冲突吗
CSS和js会阻塞页面的解析吗
CSS 是页面渲染的关键因素之一,(当页面存在外链 CSS 时,)浏览器会等待全部的 CSS 下载及解析完成后再渲染页面。关键路径上的任何延迟都会影响首屏时间,因而我们需要尽快地将 CSS 传输到用户的设备,否则,(在页面渲染之前,)用户只能看到一个空白的屏幕。
css在加载过程中不会影响到DOM树的生成,但是会影响到Render树的生成,进而影响到layout,所以一般来说,style的link标签需要尽量放在head里面,因为在解析DOM树的时候是自上而下的,而css样式又是通过异步加载的,这样的话,解析DOM树下的body节点和加载css样式能尽可能的并行,加快Render树的生成的速度。
js脚本应该放在底部,原因在于js线程与GUI渲染线程是互斥的关系,如果js放在首部,当下载执行js的时候,会影响渲染行程绘制页面,js的作用主要是处理交互,而交互必须得先让页面呈现才能进行,所以为了保证用户体验,尽量让页面先绘制出来。
link 与@import 的区别
link是HTML方式,@import是CSS方式
link最大限度支持并行下载,@import过多嵌套导致串行下载,出现FOUC
link可通过rel = "alternate stylesheet"指定候选样式
link引用CSS时,在页面载入时同时加载;@import需要页面网页完全载入以后加载。
link无兼容问题;@import是在CSS2.1提出的,低版本的浏览器不支持。
@import必须在样式规则之前,可以在css文件种引用其他文件
link支持使用Javascript控制DOM去改变样式;而@import不支持
link 优于 @import
FOUC(Flash Of Unstyled Content):用户自定义样式表加载之前浏览器使用默认样式显示文档,用户样式加载渲染之后再重新显示文档,造成页面闪烁。
解决方法:把样式表放到文档的head
不建议使用@import主要有以下两点原因:
首先,使用@import引入CSS会影响浏览器的并行下载。使用@import引用的CSS文件只有在引用它的那个css文件被下载、解析之后,浏览器才会知道还有另外一个css需要下载,这时才去下载,然后下载后开始解析、构建render tree等一系列操作。这就导致浏览器无法并行下载所需的样式文件。
其次,多个@import会导致下载顺序紊乱。在IE中,@import会引发资源文件的下载顺序被打乱,即排列在@import后面的js文件先于@import下载,并且打乱甚至破坏@import自身的并行下载。
如何设置点击盒子时给盒子外加一个边框
outline
div{border-top:1px solid #000}
1、border这个属性,例子:border:1px solid grey; 2、box-shadow这个属性,例子:box-shadow:0 0 3px grey;
display:none; 与 visibility:hidden; 的区别
都是让元素不可见
区别:
display:none;会让元素完全从渲染树中消失,渲染的时候不占据任何空间;
visibility: hidden;不会让元素从渲染树消失,渲染时元素继续占据空间,只是内容不可见
display: none;是非继承属性,子孙节点消失由于元素从渲染树消失造成,通过修改子孙节点属性无法显示;
visibility: hidden;是继承属性,子孙节点消失由于继承了hidden,通过设置visibility: visible;可以让子孙节点显式
修改常规流中元素的display通常会造成文档重排。修改visibility属性只会造成本元素的重绘。
读屏器不会读取display: none;元素内容;会读取visibility: hidden;元素内容
元素的隐藏方式?有什么区别?
visibility:hidden、display:none、z-index=-1、opacity:0
opacity:0,该元素隐藏起来了,但不会改变页面布局,并且,如果该元素已经绑定了一些事件,如click事件也能触发
visibility:hidden,该元素隐藏起来了,但不会改变页面布局,但是不会触发该元素已经绑定的事件
display:none, 把元素隐藏起来,并且会改变页面布局,可以理解成在页面中把该元素删掉
z-index=-1置于其他元素下面
盒子模型,标准盒子和ie盒子的区别 ♥
盒模型从内到外依次是啥:
- element:元素
- padding:内边距
- border:边框
- margin:外边距 这些元素组合起来构成了一个盒子,所以叫做css的盒模型
两者的区别在于content的不同,IE盒模型的content包括border、padding
box-sizing: content-box(W3C盒模型,又名标准盒模型):元素的宽高大小表现为内容的大小。 box-sizing: border-box(IE盒模型,又名怪异盒模型):元素的宽高表现为内容 + 内边距 + 边框的大小。背景会延伸到边框的外沿。
当使用inherit时:页面将从父元素继承box-sizing的值
flex布局 ♥ ♥
采用 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器"。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称“项目”。
flex :1是什么?
flex属性是 flex-grow、flex-shrink、flex-basis三个属性的缩写。
第一个参数表示: flex-grow 定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大
第二个参数表示: flex-shrink 定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小
第三个参数表示: flex-basis给上面两个属性分配多余空间之前, 计算项目是否有多余空间, 默认值为 auto, 即项目本身的大小,指定了 flex 元素在主轴方向上的初始大小。如果不使用 box-sizing 来改变盒模型的话,那么这个属性就决定了 flex 元素的内容盒(content-box)的宽或者高(取决于主轴的方向)的尺寸大小。
flex: 1; === flex: 1 1 0;但是在 chrome 浏览器上设置 flex: 1 1 0; 时, 它会自动加一个单位 px
均匀分配元素,flex:1 1 auto
在一个div中有三个子div,设置flex:1会达到什么效果呢? 我当时说的 宽度会平分
所以flex属性的默认值为:0 1 auto (不放大会缩小)
flex为none:0 0 auto (不放大也不缩小)
flex为auto:1 1 auto (放大且缩小)
很多div怎样让最后一个靠右
给父盒子开启弹性布局,然后给最后一个div加上margin-left:auto即可.同理,想让第一个div靠左,其它所有div靠右只需给第一个div设置margin-right:auto即可.
position有哪些值,这些值有哪些区别? position有哪些属性,跟父级元素是如何相对定位的?根据X和Y坐标吗?
如果父元素全是static,absolute相对于什么定位
absolute和relative哪个会使元素脱离文档流 ♥
还有什么可以让元素脱离文档流
文档流就是指元素在 HTML 文档中位置顺序决定排布的过程
可以使用 float、absolute/fixed 来脱离文档流。脱离文档流的元素不受文档流内元素的影响。
使用float脱离文档流时,其他盒子会无视这个元素,但其他盒子内的文本依然会为这个元素让出位置,环绕在该元素的周围。
因为使用absolute脱离文档流后的元素,是相对于该元素的父类(及以上,如果直系父类元素不满足条件则继续向上查询)元素进行定位的,
fixed完全脱离文档流,相对于浏览器窗口进行定位。(相对于浏览器窗口就是相对于html)。
相对定位和绝对定位 ♥ ♥ ♥
-
绝对定位:是相对于元素最近的已定位的祖先元素( 即是设置了绝对定位或者相对定位的祖先元素)。如果元素没有已定位的祖先元素,那么它的位置则是相对于最初的包含块(body) ,完全脱离了标准文档流。
绝对定位与文档流无关,所以它们可以覆盖页面上其他的元素,可以通过z-index属性来控制这些层的对方顺序。
-
相对定位:是相对于元素在文档中的初始位置;
注意,在使用相对定位时,无论是否进行移动,元素仍然占据原来的空间。因此,移动元素会导致它覆盖其它框。
-
fixed : 固定定位的元素会相对于视窗来定位,这意味着即便页面滚动,它还是会停留在相同的位置。一个固定定位元素不会保留它原本在页面应有的空隙。 脱离标准流。
不同点:absolute的”根元素“是可以设置的,fixed的“根元素”固定为浏览器窗口
注意:position:absolute,float会隐式地改变display的类型(display:none除外)。即是当元素设置position:absolute、float:left、float:right中任意一个时,都会让元素以display:inline-block的方式显示(特点是:可以设置长宽,默认宽度不占满父元素)。这时,即使故意设置display:inline; display:block都是无效的。
但是float在IE6下的双边距bug就是用display:inline; 来解决的。
position:relative不会隐式改变display的类型。
absolute:生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位
fixed:生成绝对定位的元素,相对于浏览器窗口进行定位
relative:生成相对定位的元素,相对于其正常位置进行定位
static 默认值。没有定位,元素出现在正常的流中
inherit 规定从父元素继承 position 属性的值
CSS3动画属性 ♥
transition : 平衡过渡
一般transition通过鼠标事件触发 ,如(hover)产生动画效果
animation: 动画
animation一般通过@keframes关键帧的规则来创建动画,可以通过关键字"from"和“to”,或者通过自己定义的百分比进行动画 0%是开始100%是结束
transform: 改变元素的大小、位置
translate:移动
translate(x,y) 定义2D空间
translate(x,y,z) 定义3D空间
这个的移动值可以使用像素px支持负值
scale:放大
scale(数值)定义图片放几倍大(0为不显示,1则是图片原本的大小)
rotate:旋转
rotate(x,y) 定义2D空间
rotate(x,y,z) 定义3D空间
这个的旋转值使用deg 旋转了多少度,支持负值
CSS 中transition和animate有何区别? animate 如何停留在最后一帧!
transition一般用来做过渡的, 没时间轴的概念, 通过事件触发(一次),没中间状态(只有开始和结束)
而animate则是做动效,有时间轴的概念(帧可控),可以重复触发和有中间状态;
过渡的开销比动效小,前者一般用于交互居多,后者用于活动页居多;
Animation和transition大部分属性是相同的,他们都是随时间改变元素的属性值,他们的主要区别是transition需要触发一个事件才能改变属性,而animation不需要触发任何事件的情况下才会随时间改变属性值,并且transition为2帧,从from .... to,而animation可以一帧一帧的。
至于如何让animate停留在最后一帧也好办,就它自身参数的一个值就可以了
animation-fill-mode: forwards;
<!--backwards则停留在首帧,both是轮流--> fill-mode 一般用来处理停留在某一帧
CSS选择器,及优先级 ♥
CSS三大特性—— 继承、 优先级和层叠。
继承:即子类元素继承父类的样式;
优先级:是指不同类别样式的权重比较;
层叠:是说当数量相同时,通过层叠(后者覆盖前者)的样式。
总结排序:!important > 行内样式>ID选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性,
优先级就近原则,【同权重情况下样式定义最近者为准】;【载入样式以最后载入的定位为准】
!important
内联样式style=""
ID选择器#id
类选择器/属性选择器/伪类选择器.class.active[href=""]
元素选择器/关系选择器/伪元素选择器html+div>span::after
通配符选择器*
CSS有哪些继承属性
1、关于文字排版的属性:
font、word-break、letter-spacing、text-align、text-rendering、word-spacing、white-space、text-indent、text-transform、text-shadow、font-size、font-weight
2、line-height
3、color
4、visibility
5、cursor
不可继承的一般是会改变盒子模型的:`display,margin、border、padding、height等`
怎么画正方形,三角形,同心圆
把上、左、右三条边隐藏掉(颜色设为 transparent)
#demo {
width: 0;
height: 0;
border-width: 20px;
border-style: solid;
border-color: transparent transparent red transparent;
}
css实现一个三角形箭头
css画一个圆形,如何用一个div画一个同心圆(用:before 或:after)
sass和less , sass如何转换成css代码?
给元素添加样式有哪些方法?
BFC产生的条件,特点 ❤❤
文档流其实分为定位流、浮动流和普通流三种。而普通流其实就是指BFC中的FC。
BFC 全称为块级格式化上下文 (Block Formatting Context) 。BFC是 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位以及与其他元素的关系和相互作用,当涉及到可视化布局的时候,Block Formatting Context提供了一个环境,HTML元素在这个环境中按照一定规则进行布局。
一个环境中的元素不会影响到其它环境中的布局。比如浮动元素会形成BFC,浮动元素内部子元素的主要受该浮动元素影响,两个浮动元素之间是互不影响的。这里有点类似一个BFC就是一个独立的行政单位的意思。可以说BFC就是一个作用范围,把它理解成是一个独立的容器,并且这个容器里box的布局与这个容器外的box毫不相干。
创建规则/形成BFC的条件:
根元素或其它包含它的元素;
浮动 (元素的float不为none);
绝对定位元素 (元素的position为absolute或fixed);
行内块inline-blocks(元素的 display: inline-block);
表格单元格(元素的display: table-cell,HTML表格单元格默认属性);
overflow的值不为visible的元素;
弹性盒 flex boxes (元素的display: flex或inline-flex);
但其中,最常见的就是overflow:hidden、float:left/right、position:absolute。也就是说,每次看到这些属性的时候,就代表了该元素以及创建了一个BFC了。
注意,是这些元素创建了块格式化上下文,它们本身不是块格式化上下文。
渲染规则:
1、内部的块级元素会在垂直方向,一个接一个地放置。
2、块级元素垂直方向的距离由margin决定。属于同一个BFC的两个相邻块级元素的margin会发生重叠。
3、对于从左往右的格式化,每个元素(块级元素与行内元素)的左边缘,与包含块的左边缘相接触,(对于从右往左的格式化则相反)。即使包含块中的元素存在浮动也是如此,除非其中元素再生成一个BFC。
4、BFC的区域不会与浮动元素重叠。
5、BFC是一个隔离的独立容器,容器里面的子元素和外面的元素互不影响。
6、计算BFC容器的高度时,浮动元素也参与计算。
作用:
可以包含浮动元素
不被浮动元素覆盖
阻止父子元素的margin折叠
应用:
1)防止margin重叠(塌陷)
BFC渲染规则第2点(属于同一个BFC的两个相邻块级元素的margin会发生重叠),那么不属于同一个BFC的两个相邻块级元素的margin就不会发生重叠。
2)清除浮动
计算BFC高度(清除浮动解决高度塌陷)--根据BFC的渲染规则第6点(计算BFC容器的高度时,浮动元素也参与计算)来清除浮动,解决高度坍塌的问题。
3)实现自适应两栏布局
自适应两栏布局,是一个主内容区域和一个侧边栏区域组成,两个区域的宽度都可以随窗口大小自适应。有很多种写法可以实现。
根据规则1,要先把.sider div写在.main div前面。这个.sider div才会浮动起来覆盖在.main div上面。
再根据规则4(BFC的区域不会与浮动元素重叠),给.main加上overflow:auto;触发.main div生成BFC。
1)利用 clear 属性清除浮动。
2)使父容器形成 BFC。
给父元素 .container 加一句 overflow:hidden 触发 bfc。
BFC的一个最重要的效果是,让处于BFC内部的元素与外部的元素相互隔离,使内外元素的定位不会相互影响。这是利用BFC清除浮动所利用的特性
BFC的最显著的效果就是建立一个隔离的空间,断绝空间内外元素间相互的作用。
清除浮动的方式
1、使用空标签清除浮动clear:both(缺点,增加无意义的标签)
2、给父元素添加 overflow:hidden 或者 auto 样式,触发BFC。
3、使用伪元素,也是在元素末尾添加一个点并带有 clear: both 属性的元素实现的。(推荐❤)
用after伪元素清除浮动(IE8以上和非IE浏览器才支持,目前:大型网站都有使用
.clearfix{
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
清除浮动的原理: clear:both
clear是CSS中的定位属性,规定元素的哪一侧不允许其他浮动元素。那么clear:both就是规定在左右两侧均不允许浮动元素。
clear属性只能在块级元素上其作用,这就是清除浮动样式中display:block的作用。
另外visibility: hidden;height: 0;只要content的值为空。写不写都无所谓。
那么为什么要清除浮动,最常见的是因为外层容器高度坍塌
img标签中title和alt标签的区别,有什么用
alt属性是图片因为某种原因不能加载时在页面显示的提示信息,它会直接输出在原本加载图片的地方。
title属性是在你鼠标悬停在该图片上时显示一个小提示,鼠标离开就没有了,有点类似jQuery的hover,你可以自己试试,另外,HTML的绝大多数标签都支持title属性,title属性就是专门做提示信息的。
alt是<img>的特有属性,是图片内容的等价描述,用于图片无法加载时显示、读屏器阅读图片。可提图片高可访问性,除了纯装饰图片外都必须设置有意义的值,搜索引擎会重点分析。
如果img的图片获取不到,怎么设置默认图片
好像img标签有一个错误事件可以设置
可以给 img 标签设置一个 onerror 属性,可以在 src 路径不存在时显示指定的默认图片。
href 和src的区别 ♥
1、href是Hypertext Reference的缩写,表示超文本引用。用来建立当前元素和文档之间的链接。常用的有:link、a。
<link href="reset.css" rel=”stylesheet“/>
浏览器会识别该文档为css文档,并行下载该文档,并且不会停止对当前文档的处理(即不会阻止浏览器的渲染)。这也是建议使用link,而不采用@import加载css的原因。
2、src是source的缩写,src的内容是页面必不可少的一部分,是引入。src指向的内容会嵌入到文档中当前标签所在的位置。常用的有:img、script、iframe。例如:
<script src="script.js"></script>
当浏览器解析到该元素时,会暂停浏览器的渲染,直到该资源加载完毕才继续下面的执行。这也是将js脚本放在底部而不是头部得原因。
src用于替换当前元素;href用于在当前文档和引用资源之间建立联系。
除了px外,还有哪些常见的单位
rem 相对于根字体大小的单位,比如可以设置html { font-size: 100px;}
em 相对于font-size,以父元素为基准,比如font-size:16px(浏览器默认),则2em=32px
vw 即viewpoint width,视窗宽度,比如1vm的宽度为相对于视窗的宽度的百分之一
vh 即viewpoint height ,同上
vh和vw是相对于视口的高度和宽度,而不是父元素的。%单位是相对于包含它的最近的父元素的宽度和高度。
常用布局方式
固定布局、流式布局、弹性布局、浮动布局、定位布局
浏览器兼容性问题有哪些?原因?解决办法
* png24位的图片在iE6浏览器上出现背景,解决方案是做成PNG8.
* 浏览器默认的margin和padding不同。解决方案是加一个全局的*{margin:0;padding:0;}来统一。
* IE6双边距bug:块属性标签float后,又有横行的margin情况下,在ie6显示margin比设置的大。
浮动ie产生的双倍距离 #box{ float:left; width:10px; margin:0 0 0 100px;}
这种情况之下IE会产生20px的距离,解决方案是在float的标签样式控制中加入 ——_display:inline;将其转化为行内属性。(_这个符号只有ie6会识别)
渐进识别的方式,从总体中逐渐排除局部。
首先,巧妙的使用“\9”这一标记,将IE游览器从所有情况中分离出来。
接着,再次使用“+”将IE8和IE7、IE6分离开来,这样IE8已经独立识别。
css
.bb{
background-color:red;/*所有识别*/
background-color:#00deff\9; /*IE6、7、8识别*/
+background-color:#a200ff;/*IE6、7识别*/
_background-color:#1e0bd1;/*IE6识别*/
}
* IE下,可以使用获取常规属性的方法来获取自定义属性,
也可以使用getAttribute()获取自定义属性;
Firefox下,只能使用getAttribute()获取自定义属性。
解决方法:统一通过getAttribute()获取自定义属性。
* IE下,even对象有x,y属性,但是没有pageX,pageY属性;
Firefox下,event对象有pageX,pageY属性,但是没有x,y属性。
* 解决方法:(条件注释)缺点是在IE浏览器下可能会增加额外的HTTP请求数。
* Chrome 中文界面下默认会将小于 12px 的文本强制按照 12px 显示,
可通过加入 CSS 属性 -webkit-text-size-adjust: none; 解决。
超链接访问过后hover样式就不出现了 被点击访问过的超链接样式不在具有hover和active了解决方法是改变CSS属性的排列顺序:
L-V-H-A : a:link {} a:visited {} a:hover {} a:active {}
display:inline-block什么时候会显示间隙?
移除空格、使用margin负值、使用font-size:0、letter-spacing、word-spacing
写一下双飞翼布局,两边固定中间自适应
-
圣杯布局
-
双飞翼布局
JS
let var const区别 ,暂时性死区,const定义的可以修改吗? ♥ ♥
-
var 是创建和初始化的过程都提升了,所以提前访问得到 undefined。
-
let 只是创建过程提升,提前访问报错 xx is not defined,这其实是暂时性死区的表现
-
let和const都是块级作用域,不存在变量前提
-
const是声明常量,不允许改变。但是const定义的是一个对象,keep的仅仅是对象的地址,对象内的属性依旧可以被改变。
-
暂时性死区指的是在被let或const定义的变量,在该变量被声明之前无法被访问,会报错
箭头函数,与普通函数的区别 ♥ ♥ ♥ ♥ ♥
没有arguments,那怎么接受不定参数
箭头函数是匿名函数,不能作为构造函数,不能使用new
箭头函数不绑定arguments,取而代之用rest参数...解决
箭头函数不绑定this,会捕获其所在的上下文的this值,作为自己的this值
箭头函数通过 call() 或 apply() 方法调用一个函数时,只传入了一个参数,对 this 并没有影响。
箭头函数没有原型属性
箭头函数不能当做Generator函数,不能使用yield关键字
不能使用call、apply、bind改变箭头函数中this指向 Set数据结构,数组去重
总结:
箭头函数的 this 永远指向其上下文的 this ,任何方法都改变不了其指向,如 call() , bind() , apply()
普通函数的this指向调用它的那个对象
说说this,箭头函数的this指向 ♥
new一个对象的过程,new是怎么实现的 ♥ ♥
new 操作符新建了一个空对象,这个对象原型指向构造函数的prototype,执行构造函数后返回这个对象。
bind的使用方法和注意事项、call和apply的区别,应用场景
三个函数的作用都是将函数绑定到上下文中,用来改变函数中this的指向;三者的不同点在于语法的不同。
fun.call(thisArg[, arg1[, arg2[, ...]]])
fun.apply(thisArg, [argsArray])
apply和call的区别:call方法接受的是若干个参数列表,而apply接收的是一个包含多个参数的数组。
bind()方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。
var bindFn = fun.bind(thisArg[, arg1[, arg2[, ...]]])
bindFn()
了解那些数据结构?
Promise(非实例化的promise)的方法 ,原理 ,状态 ♥ ♥ ♥
promise共有三个状态:pending(执行中)、success(成功)、rejected(失败)
一些需要注意的小点,如下
在 Pending 转为另外两种之一的状态时候,状态不可在改变..
Promise的 then为异步.而(new Promise())构造函数内为同步
Promise的catch不能捕获任意情况的错误(比如 then 里面的setTimout内手动抛出一个Error)
Promise的then返回Promise.reject()会中断链式调用
Promise的 resolve若是传入值而非函数,会发生值穿透的现象
Promise的catch还是then,return的都是一个新的 Promise(在 Promise 没有被中断的情况下)
all race resolve reject finally
讲讲all , 实现思路 ♥ ♥ ♥ ♥ ♥
all里面的promise如果有一个失败了,后面的then还能执行吗?
then不能执行,解决方法:给传入的promise加catch或者promise.al;lsettled
race 的应用:设置网络请求deadline
all与race的作用
如果有两个异步任务,任意一个任务完成了就执行,用什么方法(promise.race())
promise的优缺点,api
promise的缺点
1、无法取消Promise,一旦新建它就会立即执行,无法中途取消。
2、如果不设置回调函数,promise内部抛出的错误,不会反应到外部。
3、当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
promis的优点
1.解决回调地狱(Callback Hell)问题
(1)有时我们要进行一些相互间有依赖关系的异步操作,比如有多个请求,后一个的请求需要上一次请求的返回结果。过去常规做法只能 callback 层层嵌套,但嵌套层数过多的话就会有 callback hell 问题。比如下面代码,可读性和维护性都很差的。
(2)如果使用 promises 的话,代码就会变得扁平且更可读了。前面提到 then 返回了一个 promise,因此我们可以将 then 的调用不停地串连起来。其中 then 返回的 promise 装载了由调用返回的值。
2,更好地进行错误捕获
多重嵌套 callback 除了会造成上面讲的代码缩进问题,更可怕的是可能会造成无法捕获异常或异常捕获不可控。
(1)比如下面代码我们使用 setTimeout 模拟异步操作,在其中抛出了个异常。但由于异步回调中,回调函数的执行栈与原函数分离开,导致外部无法抓住异常。
(2)如果使用 promises 的话,通过 reject 方法把 Promise 的状态置为 rejected,这样我们在 then 中就能捕捉到,然后执行“失败”情况的回调。
promise如何捕获错误?promise可以用try catch吗?
async await原理
async await 与promise 的区别 ♥ ♥
可以把 async 看成将函数返回值使用 Promise.resolve() 包裹了下。
await 只能在 async 函数中使用
Async await本身就会包上一层Promise.resolve再return promise就重复了
async和Generator之间的区别
async promise setTimeout执行顺序, 如果await后面还是个async会产生什么问题就执行顺序来说?
Axios原理,与fetch的区别
setTimeout后面的时间为0表示什么?那如果setTimeout后面的时间设为6秒那它一定会是6秒之后执行吗?不一定,要考虑宏任务里面的耗时操作
数组遍历方法,实现方法的不同点在哪儿?♥ ♥ ♥
数组有哪些方法(es6中又有哪些)♥
filter、map和forEach区别 ♥ ♥ ♥
forEach 返回什么
forEach没有返回值,不能break、continue
forEach:没有返回值,只是对每个元素进行操作
map和filter都有。
map返回一个新的数组,将元素进行处理后返回到新数组。
filter适合得筛选后才能返回出去的数组
forEach和for循环的区别 ,性能比较
forEach和for循环都去使用return会达到什么效果
说说 for in 与 for of的区别 ♥ ♥
1.推荐在循环对象属性的时候,使用for...in,在遍历数组的时候的时候使用for...of 2.for...in循环出的是key,for...of循环出的是value 3.注意,for...of是ES6新引入的特性。修复了ES5引入的for...in的不足 4.for...of不能循环普通的对象,需要通过和Object.keys()搭配使用
遍历对象属性的方法
如何实现map
Array.prototype.map = function() = > {}
JS的数据类型,判断数据类型的方法 ♥ ♥ ♥ ♥ ♥
Undefined、Null、Boolean、Number、String、新增:Symbol
判断数据类型的方法:
1、typeof
优点:能够快速区分基本数据类型 缺点:不能将Object、Array和Null区分,都返回object
2、instanceof
优点:能够区分Array、Object和Function,适合用于判断自定义的类实例对象 缺点:Number,Boolean,String基本数据类型不能判断
3、Object.prototype.toString.call()
优点:精准判断数据类型 缺点:写法繁琐不容易记,推荐进行封装后使用
var toString = Object.prototype.toString;
console.log(toString.call(2)); //[object Number]
console.log(toString.call(true)); //[object Boolean]
console.log(toString.call('str')); //[object String]
console.log(toString.call([])); //[object Array]
console.log(toString.call(function(){})); //[object Function]
console.log(toString.call({})); //[object Object]
console.log(toString.call(undefined)); //[object Undefined]
console.log(toString.call(null)); //[object Null]
不同点: typeof 返回值是一个字符串,用来说明变量的数据类型 instanceof 用于判断一个变量是否属于某个对象的实例.
null 和 undefined的区别
相同点:
在 if判断语句中,值都默认为 false
大体上两者都是代表无,具体看差异
差异:
null转为数字类型值为0,而undefined转为数字类型为 NaN(Not a Number)
undefined是代表调用一个值而该值却没有赋值,这时候默认则为undefined
null是一个很特殊的对象,最为常见的一个用法就是作为参数传入(说明该参数不是对象)
设置为null的变量或者对象会被内存收集器回收
JS有几种类型的值?
栈:原始数据类型(Undefined,Null,Boolean,Number、String)
堆:引用数据类型(对象、数组和函数)
两种类型的区别是:存储位置不同;
原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体
基本数据类型中的symbol的应用场景
如何判断数组,instanceof原理?
原型链,用原型链会有一个问题,有个object,我把它的原型链指向数组,那怎么判断呢
1、instanceof方法
instanceof 运算符是用来测试一个对象是否在其原型链原型构造函数的属性
2、constructor方法
constructor属性返回对创建此对象的数组函数的引用,就是返回对象相对应的构造函数
3、最简单的方法,这种写法兼容性最好使用Object.prototype.toString.call()
4、ES5新增方法isArray()
定义函数的方法
js数组与字符串的api,字符串和数组互转 ,哪些方法会改变原数组 ♥
数组reduce方法
给字符串,怎么找到想要对应字符的位置,有哪些方法?
继承有哪些?如何继承 ♥ ♥
1、原型链继承
new了一个空对象,这个空对象指向Animal并且Cat.prototype指向了这个空对象,这种就是基于原型链的继承。
特点:基于原型链,既是父类的实例,也是子类的实例。
缺点:1.无法实现多继承;2.所有新实例都会共享父类实例的属性。
2、构造继承
特点:可以实现多继承(call多个),解决了所有实例共享父类实例属性的问题。
缺点:1.只能继承父类实例的属性和方法;2.不能继承原型上的属性和方法。
3、组合继承
特点:可以继承实例属性/方法,也可以继承原型属性/方法
缺点:调用了两次父类构造函数,生成了两份实例
答: 有以下六种方法
1.原型链继承 JavaScript实现继承的基本思想:通过原型将一个引用类型继承另一个引用类型的属性和方法。
2.借用构造函数继承(伪造对象或经典继承) JavaScript实现继承的基本思想:在子类构造函数内部调用超类型构造函数。 通过使用apply()和call()方法可以在新创建的子类对象上执行构造函数。
3.组合继承(原型+借用构造)(伪经典继承) JavaScript实现继承的基本思想:将原型链和借用构造函数的技术组合在一块,从而发挥两者之长的一种继承模式。
将原型链和借用构造函数的技术组合到一起,从而取长补短发挥两者长处的一种继承模式。
4.原型式继承 JavaScript实现继承的基本思想:借助原型可以基于已有的对象创建新对象,同时还不必须因此创建自定义的类型。
5.寄生式继承 JavaScript实现继承的基本思想:创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真正是它做了所有工作一样返回对象。
寄生式继承是原型式继承的加强版。
6.寄生组合式继承 JavaScript实现继承的基本思想:通过借用函数来继承属性,通过原型链的混成形式来继承方法。
原型和原型链, prototype 与—proto-的区别 ♥ ♥ ♥
每个对象都会在其内部初始化一个属性,就是prototype(原型),当我们访问一个对象的属性时,
如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,
于是就这样一直找下去,也就是我们平时所说的原型链的概念。
关系:instance.constructor.prototype = instance.__proto__
特点:
JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。
把所有的对象共用的属性全部放在堆内存的一个对象(共用属性组成的对象),然后让每一个对象的 __proto__存储这个「共用属性组成的对象」的地址。而这个共用属性就是原型,原型出现的目的就是为了减少不必要的内存消耗。而原型链就是对象通过__proto__向当前实例所属类的原型上查找属性或方法的机制,如果找到Object的原型上还是没有找到想要的属性或者是方法则查找结束,最终会返回undefined
当我们需要一个属性的时,Javascript引擎会先看当前对象中是否有这个属性, 如果没有的话,
就会查找他的Prototype对象是否有这个属性,如此递推下去,一直检索到 Object 内建对象。
function Func(){}
Func.prototype.name = "Sean";
Func.prototype.getInfo = function() {
return this.name;
}
var person = new Func();//现在可以参考var person = Object.create(oldObject);
console.log(person.getInfo());//它拥有了Func的属性和方法
//"Sean"
console.log(Func.prototype);
// Func { name="Sean", getInfo=function()}
获取原型的方法
如果属性一直往下找,找不到的话是什么?(undefined)
判断是否是一个数组的方法
事件冒泡,事件委托,事件捕获,默认是捕获还是冒泡 ♥ ♥
事件委托的时候如何知道是哪个子元素 e.target e.currentTarget ???
target 是触发事件的对象,点击的对象. 而currentTarget是触发绑定的对象,也就是向上冒泡触发的对象
事件委托,但是vue又直接在标签上写事件,这种事为什么呢?
在DOM标准事件模型中,是先捕获后冒泡。但是如果要实现先冒泡后捕获的效果,对于同一个事件,监听捕获和冒泡,分别对应相应的处理函数,监听到捕获事件,先暂缓执行,直到冒泡事件被捕获后再执行捕获之间。
简介:事件委托指的是,不在事件的发生地(直接dom)上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判断事件发生元素DOM的类型,来做出不同的响应。
举例:最经典的就是ul和li标签的事件监听,比如我们在添加事件时候,采用事件委托机制,不会在li标签上直接添加,而是在ul父元素上添加。
好处:比较合适动态元素的绑定,新添加的子元素也会有监听函数,也可以有事件触发机制。
事件循环,node的事件循环和js的区别 ♥ ♥
JS是单线程的,为了防止一个函数执行时间过长阻塞后面的代码,所以会先将同步代码压入执行栈中,依次执行,将异步代码推入异步队列,异步队列又分为宏任务队列和微任务队列,因为宏任务队列的执行时间较长,所以微任务队列要优先于宏任务队列。微任务队列的代表就是,Promise.then,MutationObserver,宏任务的话就是setImmediate setTimeout setInterval
dom树遍历
- 如果元素类型发生变化,直接替换
- 如果是文本,则比较文本里面的内容,是否有差异,如果是元素就需要比较当前元素的属性是否相等,会先比较key, 在比较类型 为什么 react中循环 建议不要使用索引 ,如果纯为了展示 那可以使用索引
dom获得节点、移除、添加节点的方式
事件绑定 addEventListener方法有几个参数,最右一个参数表示什么?
js精度处理问题
parseFloat((0.1 + 0.2).toFixed(10))
js垃圾回收机制
JS的垃圾回收机制是为了以防内存泄漏,内存泄漏的含义就是当已经不需要某块内存时这块内存还存在着,垃圾回收机制就是间歇的不定期的寻找到不再使用的变量,并释放掉它们所指向的内存。
JS中最常见的垃圾回收方式是标记清除。
工作原理:是当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。
工作流程:
垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记。
去掉环境中的变量以及被环境中的变量引用的变量的标记。
再被加上标记的会被视为准备删除的变量。
垃圾回收器完成内存清除工作,销毁那些带标记的值并回收他们所占用的内存空间。
对象合并
js文件引入的方式?为什么要放在文件底部?
require和import的区别 ♥ ♥
了解前端工程化吗?
手写:实现一个简单的Set类,包含add和remove方法
柯里化函数,一行,把什么样的输入转变成什么样的输出
答:是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。 把接受多个参数的函数转换成接受一个单一参数的函数
JSON.parse(JSON.stringify())有什么弊端,什么类型的数据是不能拷贝的
0.1+0.2!=0.3怎么处理
把需要计算的数字升级(乘以10的n次幂)成计算机能够精确识别的整数,等计算完成后再进行降级(除以10的n次幂),即:
(0.1*10 + 0.2*10)/10 == 0.3 //true
网络
状态码有哪些?作用是什么?♥ ♥
403 404,出现404是什么问题?是服务器的问题吗?
403是服务器禁止访问,404是服务器没找到文件或目录。
导致4错误的原因
1、Web服务扩展锁定策略阻止本请求。
2、无法在所请求的端口上访问Web站点。
3、MIME映射策略阻止本请求。
4、跟踪访问的各类脚码或CSS文件无效但调用代码依然存在。
5、某个目录直接删除(导致一段时间该目录的文件在被爬行时全部报404 Not Found错误)
6、网站更新改版,但某些局部板块沿用原来的模块,而原有的模块调用的文件已经被删除或转移了路径。
7、网页URL生成规则改变、网页文件更名或移动位置、导入链接拼写错误等,导致原来的URL地址无法访问
请求头里边都有什么?
Accept:指定客户端能够接收的内容类型。
Accept-Charset:浏览器可以接受的字符编码集。
Accept-Encoding:指定浏览器可以支持的web服务器返回内容压缩编码类型。
Accept-Language:浏览器可接受的语言。
Accept-Ranges:可以请求网页实体的一个或者多个子范围字段。
AuthorizationHTTP:授权的授权证书。
Cache-Control:指定请求和响应遵循的缓存机制。
Connection:表示是否需要持久连接。(HTTP 1.1默认进行持久连接)
CookieHTTP:请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。
Content-Length:请求的内容长度。
Content-Type:请求的与实体对应的MIME信息。
Date:请求发送的日期和时间。
Expect:请求的特定的服务器行为。
From:发出请求的用户的Email。
Host:指定请求的服务器的域名和端口号。
If-Match:只有请求内容与实体相匹配才有效。
If-Modified-Since:如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码。
If-None-Match:如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变。
If-Range:如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。
If-Unmodified-Since:只在实体在指定时间之后未被修改才请求成功。
Max-Forwards:限制信息通过代理和网关传送的时间。
Pragma:用来包含实现特定的指令。
Proxy-Authorization:连接到代理的授权证书。
Range:只请求实体的一部分,指定范围。
Referer:先前网页的地址,当前请求网页紧随其后,即来路。
TE:客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息。
Upgrade:向服务器指定某种传输协议以便服务器进行转换(如果支持。
User-AgentUser-Agent:的内容包含发出请求的用户信息。
Via:通知中间网关或代理服务器地址,通信协议。
Warning:关于消息实体的警告信息
http响应头
Accept-Ranges:表明服务器是否支持指定范围请求及哪种类型的分段请求。
Age:从原始服务器到代理缓存形成的估算时间(以秒计,非负)。
Allow:对某网络资源的有效的请求行为,不允许则返回405。
Cache-Control:告诉所有的缓存机制是否可以缓存及哪种类型。
Content-Encodingweb:服务器支持的返回内容压缩编码类型。。
Content-Language:响应体的语言。
Content-Length:响应体的长度。
Content-Location:请求资源可替代的备用的另一地址。
Content-MD5:返回资源的MD5校验值。
Content-Range:在整个返回体中本部分的字节位置。
Content-Type:返回内容的MIME类型。
Date:原始服务器消息发出的时间。
ETag:请求变量的实体标签的当前值。
Expires:响应过期的日期和时间。
Last-Modified:请求资源的最后修改时间。
Location:用来重定向接收方到非请求URL的位置来完成请求或标识新的资源。
Pragma:包括实现特定的指令,它可应用到响应链上的任何接收方。
Proxy-Authenticate:它指出认证方案和可应用到代理的该URL上的参数。
refresh:应用于重定向或一个新的资源被创造,在5秒之后重定向(由网景提出,被大部分浏览器支持)
Retry-After:如果实体暂时不可取,通知客户端在指定时间之后再次尝试。
Serverweb:服务器软件名称。
Set-Cookie:设置Http Cookie。
Trailer:指出头域在分块传输编码的尾部存在。
Transfer-Encoding:文件传输编码。
Vary:告诉下游代理是使用缓存响应还是从原始服务器请求。
Via:告知代理客户端响应是通过哪里发送的。
Warning:警告实体可能存在的问题。
WWW-Authenticate:表明客户端请求实体应该使用的授权方案。
说说浏览器缓存(HTTP缓存) ♥ ♥ ♥
浏览器存储(如果要存储一个对象,如何存储)
浏览器缓存(Browser Caching)是为了节约网络的资源加速浏览,浏览器在用户磁盘上对静态资源进行存储,当再次请求该页面时,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的阅览。而浏览器缓存,本质上就是HTTP的缓存。
1、缓存相关的请求响应头header
Expires 响应头,代表该资源的过期时间
Cache-Control 请求/响应头, 缓存控制字段,精确控制缓存策略
If-Modified-Since 请求头,资源最近修改时间,由浏览器告诉服务器
Last-Modified 响应头,资源最近修改时间,由服务器告诉浏览器
Etag 响应头,资源标识,由服务器告诉浏览器
If-None-Match 请求头,缓存资源标识符,由浏览器告诉服务器
配对使用的字段:
If-Modified-Since 和 Last-Modified
Etag 和 If-None-Match
2、http缓存分类
(1)强制缓存
分为 Expires 和 Cache-Control
Expires: 是服务器告诉浏览器的缓存过期时间(值为GMT时间,即格林尼治时间),即下一次请求时,如果浏览器端的当前时间还没有到达过期时间,则直接使用缓存数据。
虽然这种方式添加了缓存控制,节省流量,但是还是有以下几个问题的:
由于浏览器时间和服务器时间不同步,如果浏览器设置了一个很后的时间,过期时间一直没有用
缓存过期后,不管文件有没有发生变化,服务器都会再次读取文件返回给浏览器
不过Expires 是HTTP 1.0的东西,现在默认浏览器均默认使用HTTP 1.1,所以它的作用基本忽略。
Cache-Control:针对浏览器和服务器时间不同步,加入了新的缓存方案;这次服务器不是直接告诉浏览器过期时间,而是告诉一个相对时间Cache-Control=10秒,意思是10秒内,直接使用浏览器缓存。
Cache-Control默认的属性是public,常见的属性还有:
- private:客户端可以缓存
- public:客户端和代理服务器都可缓存
- max-age = xxx:缓存的内容将在xxx秒后失效
- no-cache:需要使用对比缓存来验证缓存数据
- no-store:所有内容都不会缓存,强制缓存,协商缓存都不会触发
所以我们在刷新页面的时候,如果只按F5只是单纯的发送请求,按Ctrl+F5会发现请求头上多了两个字段Pragma: no-cache和Cache-Control: no-cache。
(2)协商缓存
强制缓存每次都是根据时间来判断缓存是否过期,当到达过期时间后,如果文件没改动,再次去获取文件就有点浪费服务器的资源了。
协商缓存有两组配对使用的字段:
Last-Modified 和 If-Modified-Since
ETag 和 If-None-Match
Last-Modified: 为了节省服务器的资源,再次改进方案。浏览器和服务器协商,服务器每次返回文件的同时,告诉浏览器文件在服务器上最近的修改时间。请求过程:
+ 浏览器请求资源,服务器读取磁盘文件,返回给浏览器,同时带上文件上次修改时间Last-Modified;
+ 当浏览器上的缓存文件过期时,浏览器带上请求头If-Modified-Since(等于上一次请求的Last-Modified)请求服务器;
+ 服务器比较请求头里的If-Modified-Since和文件的上次修改时间。如果果一致就继续使用本地缓存(304),如果不一致就再次返回文件内容和Last-Modified。循环此操作
存在的问题:
由于Last-Modified修改时间是GMT时间,只能精确到秒,如果文件在1秒内有多次改动,服务器并不知道文件有改动,浏览器拿不到最新的文件;
如果服务器上文件被多次修改了但是内容却没有发生改变,服务器需要再次重新返回文件。
ETag: 为了解决文件修改时间不精确带来的问题,服务器和浏览器再次协商,这次不返回时间,返回文件的唯一标识ETag。只有当文件内容改变时,ETag才改变。请求过程如下:
+ 浏览器请求资源,服务器读取磁盘文件,返回给浏览器,同时带上文件的唯一表示ETag;
+ 当浏览器的缓存文件过期时,浏览器带上请求头If-None-Match(等于上一次请求的ETag)请求服务器;
+ 服务器比较请求头里的If-None-Match和文件的ETag,如果一致就继续使用本地缓存(304),不一致就再次返回文件内容和ETag。循环此操作
强制缓存在缓存未失效的情况下,不需要再和服务器发生交互;协商缓存需要进行比较判断是否可以使用缓存。
两类缓存规则可以同时存在,强制缓存优先级高于协商缓存 === 当执行强制缓存的规则时,如果缓存生效,直接使用缓存,不再执行协商缓存规则
缓存优先级:
Pragma > Cache-Control > Expires > ETag > Last-Modified
首先通过 Cache-Control 验证强缓存是否可用
如果强缓存可用,直接使用
否则进入协商缓存,即发送 HTTP 请求,服务器通过请求头中的If-Modified-Since或者If-None-Match这些条件请求字段检查资源是否更新
若资源更新,返回资源和200状态码
否则,返回304,告诉浏览器直接从缓存获取资源
http常见字段有哪些?
Host字段
Content-Length字段
Connection字段
Content-Type字段
Content-Enckoding字段
Content-Type值有哪些
Content-type是Http的实体首部字段,在request的请求行(或response的状态码)之后,也是首部的一部分。用于说明请求或返回的消息主体是用何种方式编码,在request header和response header里都存在。
四种常见取值:
1、application/x-www-form-urlencoded
最常见 POST 提交数据的方式。浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。
1)浏览器的原生form表单
2) 提交的数据按照 key1=val1&key2=val2 的方式进行编码,key和val都进行了URL转码
2、multipart/form-data
常见的 POST 数据提交的方式。我们在使用表单上传文件时,必须让 form 的 enctyped 等于这个值。
上面提到的这两种 POST 数据的方式,都是浏览器原生支持的,而且现阶段原生 form 表单也只支持这两种方式。但是随着越来越多的 Web 站点,尤其是 Web/App,全部使用 Ajax 进行数据交互之后,我们完全可以定义新的数据提交方式,给开发带来更多便利。
3、application/json
作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。
JSON 格式支持比键值对复杂得多的结构化数据,这一点也很有用。
4、text/xml
XML-RPC(XML Remote Procedure Call)。它是一种使用 HTTP 作为传输协议,XML 作为编码方式的远程调用规范。
eg: Content-Type: text/html; charset=utf-8
表示发送的是网页,编码是utf-8
GET和POST的区别,应用 ♥ ♥ ♥ ♥ ♥ ♥
GET方法:请求从服务器获取资源
POST方法:向URI指定的资源提交数据,数据就放在报文的body里
安全:在HTTP协议里,安全是指请求方法不会破坏服务器上的资源
幂等:多次执行相同的操作,结果都是相同的
GET方法是安全且幂等的,因为它是【只读】操作,无论操作多少次,服务器上的数据都是安全的,且每次的结果都是相同的。
POST是【新增/提交数据】的操作,会修改服务器上的资源,所以是不安全的,且多次提交数据会创建多个资源,所以不是幂等的。
从缓存的角度,GET 请求会被浏览器主动缓存下来,留下历史记录,而 POST 默认不会。
从编码的角度,GET 只能进行 URL 编码,只能接收 ASCII 字符,而 POST 没有限制。
从参数的角度,GET 一般放在 URL 中,因此不安全,POST 放在请求体中,更适合传输敏感信息。
从幂等性的角度,GET是幂等的,而POST不是。(幂等表示执行相同的操作,结果也是相同的)
从TCP的角度,GET 请求会把请求报文一次性发出去,而 POST 会分为两个 TCP 数据包,首先发 header 部分,如果服务器响应 100(continue), 然后发 body 部分。(火狐浏览器除外,它的 POST 请求只发一个 TCP 包)
补充补充一个get和post在缓存方面的区别:
get请求类似于查找的过程,用户获取数据,可以不用每次都与数据库连接,所以可以使用缓存。
post不同,post做的一般是修改和删除的工作,所以必须与数据库交互,所以不能使用缓存。因此get请求适合于请求缓存。
get请求的缓存,怎样可以不缓存
cookieds有哪些字段
1、name字段:名称
2、value字段:cookie的值
3、domain字段:为可以访问此cookie的域名,顶级域名只能设置domain为顶级域名,不能设置为二级域名或者三级域名,否则cookie无法生成。二级域名能读取设置了domain为顶级域名或者自身的cookie,不能读取其他二级域名domain的cookie。所以要想cookie在多个二级域名中共享,需要设置domain为顶级域名,这样就可以在所有二级域名里面或者到这个cookie的值了。
4、path字段:为可以访问此cookie的页面路径。 比如domain是abc.com,path是/test,那么只有/test路径下的页面可以读取此cookie。
5、Size字段:设置cookie的大小
6、http字段:cookie的httponly属性。若为true,则只有在http请求头中会带有此cookie的信息,而不能通过document.cookie来访问此cookie
7、expires/Max-Age字段:设置cookie的过期时间。不设置的话默认值是Session,意思是cookie会和session一起失效。当浏览器关闭(不是浏览器标签页,而是整个浏览器) 后,此cookie失效。
8、secure字段:设置是否只能通过https来传递此条cookie
www.xx.baidu.com(子域名)和www.baidu.com访问这两个能实现cookies共享吗?怎么实现的?
说说HttpOnly
说说Samesite
SameSite是Cookie中的一个属性用来限制第三方Cookie,从而减少安全风险。Chrome 51 开始,浏览器的Cookie新增加了一个SameSite属性,用来防止CSRF攻击和用户追踪。
它可以设置三个值:Strict Lax None
Web前端安全
从影响面看排名前两位的就是 XSS 和 CSRF,其基本原理都是攻破了浏览器同源策略的限制。
CSRF 漏洞目前的措施一般是验证 referer 或者是用安全 token。而 google 则希望从标准层面去根治这个排名第二的前端安全漏洞。其方案就是给 Cookie 新增一个属性,用这个属性来控制什么情况下可以发送 Cookie,这个属性就是我们今天要讨论的 SameSite 属性。
CSRF攻击
Cookie 往往用来存储用户的身份信息,恶意网站可以设法伪造带有正确 Cookie 的 HTTP 请求,这就是 CSRF 攻击
websocket是如何做的,连接异常和边界问题怎么处理
http1.0 ,http1.1 和http2.0的区别 ♥ ♥
http1.0
【短连接】,每发起一次请求,都要新建一次TCP三次握手,且是串行请求,做了无谓的TCP连接建立和端口,增加了通信开销
http1.1
(1)提出了【长连接】的通信方式(持久连接) --减轻了服务器端的负载
减少了TCP连接的重复建立和端口造成的额外开销,减轻了服务器端的负载
特点:只要任意一端没有明确提出断开连接,则保持TCP连接状态
(2)支持【管道网络传输】 -- 减少整体的响应时间
即在同一个TCP连接里,客户端可发起多个请求,只要一个请求发出去了,不用等其回来,直可发送第二个请求出去。但是服务器还是按照顺序回应请求,容易发生队头堵塞
(3)队头堵塞
顺序发送的请求序列中的一个请求因为某种原因被堵塞,后面排队的所有请求也一同被堵塞了,会导致客户端一直请求不到数据。
http2.0
http/2协议是基于HTTPS的,所以安全性也是有保障的
(1)头部压缩
http/2会【压缩头】,如果同时发出多个请求,他们的头是一样或者相似的,那么协议会【消除重复的部分】
(2)二进制格式 --增加了数据传输的效率
http/1.1采用的是【纯文本】形式的明文报文,HTTP/2采用【二进制格式】,头信息和数据体都是二进制,并且统称为帧:头信息帧和数据帧
(3)数据流
数据包不是按顺序发送的,每个请求或回应的所有数据包,称为一个数据流。每个数据流都标记着一个独一无二的编号,规定客户端发出的数据流编号为奇数,服务器发出的数据流编号为偶数。
客户端还可以指定数据流的优先级。
(4)多路复用
http/2可以在【一个连接中并发多个请求或回应,不用按照顺序一一对应】
移除了http/1.1中的串行请求,不需要排队等待,也不会再出现队头堵塞问题,【降低了延迟,大幅度提高了连接的利用率】
(5)服务器推送 --减少延时的等待
服务器不再是被动地响应,也可以主动向客户端发送消息
UDP不会出现http/1.1的队头堵塞和HTTP/2的一个丢包全部重传问题
基于UDP的QUIC协议可实现可靠性传输,QUIC是一个在UDP之上的伪TCP+TLS+HTTP/2的多路复用协议,是新协议
http和https的区别 , https的加密方式? https服务器为什么把公钥发送给客户端? ♥ ♥
建立连接的时候:http2比http多了TLS的握手过程,目的是为了通过非对称加密握手协商或交换出对称加密密钥,这个过程最长可以花费2RTT
传输内容的时候:https会把数据进行加密,通常是对称加密数据
SSL/TLS 是同一个东西的不同阶段,传输层安全协议
https解决了http的哪些问题?
http是明文传输,所以安全上存在三种风险:窃听风险、篡改风险、冒充风险
HTTPS在HTTP与TCP层之间加入了SSL/TLS协议,解决了上述风险:信息加密、校验机制、身份证书
HTTPS如何解决上面的三个风险:
【混合加密】的方式实现信息的机密性,解决了窃听的风险
【摘要算法】的方式实现完整性,可以校验数据的完整性
将服务器公钥放入到【数字证书】中,解决了冒充的风险
(1)混合加密
HTTPS采用对称加密和非对称加密结合的【混合加密】方式
客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密
https是如何保证安全的?
浏览器是如何保证CA证书是可靠的?
CA(数字证书认证机构)
将服务器公钥放在数字证书中,只要证书是可信的,公钥就是可信的
http传输如果有一个数据传输错误,会发生什么情况
传输错误会阻碍后面数据的传输
http2的 服务端推送 服务端怎样告诉浏览器要推送的内容
ajax请求过程,步骤,手写 ♥
1.创建ajax实例
2.执行open 确定要访问的链接 以及同步异步
3.监听请求状态
4.发送请求
ajax是如何实现的?
ajax是一种异步通信的方法,从服务端获取数据,达到局部刷新页面的效果。 过程:
- 创建
XMLHttpRequest对象; - 调用
open方法传入三个参数 请求方式(GET/POST)、url、同步异步(true/false); - 监听
onreadystatechange事件,当readystate等于4时返回responseText; - 调用send方法传递参数。
Ajax请求中readState都有哪些,代表什么
cookie、localstorage和sessionstorage的区别 ♥♥♥ 操作的api
浏览器的本地存储主要分为Cookie、WebStorage和IndexDB, 其中WebStorage又可以分为localStorage和sessionStorage。
共同点: 都是保存在浏览器端、且同源的
cookie是网站为了标识用户身份而储存在用户本地终端上的数据(通常经过加密)
cookie数据始终在同源的HTTP请求中携带(即使不需要),即会在浏览器和服务器间来回传递
sessionStorage和localStroage不会自动把数据发给服务器,仅在本地保存
存储大小:
cookie数据大小不能超过4K
其他两个有存储大小的限制,但是可以达到5M或更大
有期时间:
localStorage存储持久数据,浏览器关闭后数据不丢失除非自动删除数据
sessionStorage数据在当前浏览器关闭后自动删除
cookie设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
cookie,session怎么实现保留登录状态的,服务端客户端都怎么写的?
cookie出现解决什么问题?cookie是做什么的?token呢?token怎么生成的?
服务端是如何设置cookie过期时间的?
XMLHttpRequest对象有哪些属性?
浏览器的缓存方式有哪些?区别,应用场景,登录信息存在哪里?浏览器的历史记录在哪儿?为什么?
webstorage,及如何使其与服务端交互
前端安全和防范
TCP UDP区别 ♥ ♥ ♥
1、TCP是面向连接的,udp是无连接的,即发送数据前不需要先建立连接
2、TCP提供可靠的服务,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达(适合大数据量交换)
UDP尽最大努力交付,不保证可靠交付
3、TCP是基于字节流的传输层通信协议,UDP是面向报文,且网络出现拥塞不会使得发送速率降低(因此会出现丢包,对实时的应用比如IP电话和视频会议)
4、TCP只能是一对一,UDP支持一对一,一对多
5、TCP的首部较大为20字节,UDP头部只有8个字节(64位)
6、TCP是面向连接的可靠性传输,UDP是不可靠的
UDP不提供复杂的控制机制,利用IP提供面向无连接的通信服务,头部只有8个字节(64位)
TCP,HTTP在哪一层
三次握手,为什么不是两次?四次挥手,为什么不五次或者三次?
TCP是面向连接的协议,所以使用TCP之前必须先建立连接(通过三次握手)
【第三次握手时可以携带数据的,前两次握手是不可以携带数据的】
三次握手的原因:
阻止重复历史连接的初始化/阻止历史连接的建立(主要原因)
可以同步双方的初始化序列号
可以避免资源浪费
序列号能保证数据包不重复、不丢弃和按序传输
不使用两次握手和四次握手的原因“
两次握手:无法阻止历史连接的建立,会造成双方资源的浪费,也无法可靠的同步双方序列号
四次握手:三次握手就已经理论上最少可靠连接建立,所以不需要使用更多的通信次数
TCP断开连接时通过【四次挥手】的方式
为什么需要四次:
关闭连接时,客户端向服务器发送FIN时,仅仅表示客户端不再发送数据了但是还能接收数据
服务器收到客户端的FIN报文时,先回一个ACK应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送FIN报文给客户端来表示同意现在关闭连接。
从上面过程可知,服务端通常需要等待完成数据的发送和处理,所以服务端的ACK和FIN一般都会分开发送,比三次握手多了一次
注意:主动关闭连接的,采用TIME_WAIT状态
MSL是报文最大生存时间,超过这个时间报文就会被丢弃
TCP如何进行流量控制的?如何进行拥塞控制的?使用哪几种机制? ♥
TCP有:重传机制、滑动窗口、流量控制、拥塞控制
流量控制:让发送方根据接收方的实际接受能力控制发送的数据量
让发送发送速率不要过快,让接收方来得及接收。防止发生丢包现象。利用【滑动窗口机制】可以很方便的在TCP连接上实现对数据传输端的流量控制。原理:运用TCP报文段中的窗口大小字段来控制,发送方的发送窗口不可以大于接收方发回的窗口大小。
拥塞控制:为了避免发送方的数据填满整个网络
拥塞现象是指到达通信子网中某一部分的分组数量过多,使得该部分网络来不及处理,以致引起这部分乃至整个网络性能下降的现象,严重时甚至会导致网络通信业务陷入停顿,即出现死锁现象。
1.TCP发送方首先发送一个数据报,然后等待对方的回应
2.得到回应后就把这个窗口的大小加倍,然后连续发送两个数据报
3.直到出现超时错误,这样,发送端就了解到了通信双方的线路承载能力,也就确定了拥塞窗口的大小
拥塞控制主要是四个算法:
慢启动:当发送方每没收一个ACK,拥塞窗口cwnd的大小就会加1
拥塞避免:每收到一个ACK时,cwnd增加1/cwnd
拥塞发生
快速恢复
区别:
1 相同点
现象都是丢包;实现机制都是让发送方发的慢一点、发的少一点。
2 不同点
2.1丢包位置不同
流量控制丢包位置是在接收端上;拥塞控制丢包位置是在路由器上。
2.2作用的对象不同
流量控制的对象是接收方,怕发送方发的太快,使得接收方来不及处理;拥塞控制的对象是网络,怕发送方发的太快,造成网络拥塞,使得网络来不及处理。
3 联系
拥塞控制通常表示的是一个全局性的过程,它会涉及到网络中所有的主机、所有的路由器和降低网络传输性能的所有因素;流量控制发生在发送端和接收端之间,只是点到点之间的控制。
从输入url地址到页面相应都发生了什么?♥ ♥ ♥
1、HTTP
浏览器【对URL进行解析】,从而生成发送给Web服务器的请求消息。(URL实际上是请求服务器里的文件资源),对URL进行解析后,浏览器确定了Web服务器和文件名,根据这些信息来【生成HTTP请求消息】了
2、DNS -- 真实地址查询
进行【域名解析】,查询服务器域名对应的IP地址,因为委托操作系统发送消息时,必须提供通信对象的IP地址(就像打电话必须要知道对方的号码,但是号码难记,就通常保存姓名到通讯录里)
(域名的层级关系:根DNS服务器、顶级域DNS服务器com、权威DNS服务器server.ccom)
3、协议栈
通过DNS获取到IP后,就可以把HTTP的传输工作交给操作系统中的【协议栈】
协议栈的上半部分有两块,分别时负责收发数据的TCP和UDP协议,他们俩会接受应用层的委托执行收发数据的操作,下一部分是用IP协议控制网络包收发操作。
(1) TCP协议,传输数据之前,TCPx建立连接(三次握手)---下图
如果HTTP请求消息比较长,超过了MSS的长度,此时TCP就需要把HTTP的数据拆解称一块块的数据发送,而不是一次性发送所有数据。
双方建立连接后,TCP报文中的数据部分就是存放HTTP头部+数据,组装成TCP报文之后,交给下面的网络层处理;
(2) IP ----远程定位
TCP模块在执行连接,收发,断开等各阶段操作时,都需要委托IP模块将数据封装成网络包发送给通信对象
(3) MAC ---两点传输
生成IP头部后,接下来网络包还需在IP头部的前面加上MAC头部
MAC头部是以太网使用的头部,它包含了【接收方和发送方的MAC地址】等信息。一般在TCP/IP通信里,MAC包头的协议类型只使用:0800(IP协议)、0806(ARP协议)--以【广播获取】的形式可以找到路由器的MAC地址
4、网卡 ---出口
需要【将数字信息转换为电信息】,才能在网线上传输,这才是真正的数据发送过程。
控制网卡需要靠网卡驱动程序,网卡驱动从IP模块获取到包之后,会将其复制到网卡内的缓存区中,然后会在其开头加上报头和起始帧分界符在末尾加上用于检测错误的帧校验序列。
5、交换机 ---送别者
将网络包原样转发到目的地,交换机工作在MAC层(二层网络设备)
交换机的端口不具有MAC地址
交换机根据MAC地址表查找MAC地址,然后将信号发送到相应的端口
6、路由器
接收包,然后查询路由表确定输出端口
【在网络包传输的过程中,源IP和目标IP始终不会变,变的是MAC地址,因为需要MAC地址在以太网内进行两个设备之间的包传输】
路由器和交换机的区别:
路由器是基于IP设计的,称为三层网络设备,路由器的各个端口都具有MAC地址和IP地址
交换机是基于以太网设计的,称为二层网络设备,交换机的端口不具有MAC地址
7、TCP四次挥手
简答版:
浏览器根据请求的URL交给DNS域名解析,找到真实IP,向服务器发起请求;
服务器交给后台处理完成后返回数据,浏览器接收文件(HTML、JS、CSS、图象等);
浏览器对加载到的资源(HTML、JS、CSS等)进行语法解析,建立相应的内部数据结构(如HTML的DOM);
载入解析到的资源文件,渲染页面,完成。
当客户端有多个网卡时,就会有多个IP地址,那么IP头部的源地址应该根据路由表规则,将目标地址与路由表每个条目的子网掩码做&操作,和哪个Destination匹配,就选择对应的网卡作为IP包头得源地址。
跨域,跨域的方法有哪些?具体机制是什么,如何解决跨域?♥ ♥ ♥
浏览器遵循同源策略(协议、主机/域名、端口相同),由浏览器同源策略限制的一类请求场景叫做狭义的跨域。如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。
广义的跨域:
资源跳转: A链接、重定向、表单提交
资源嵌入: <link>、<script>、<img>、<frame>等dom标签,还有样式中background:url()、@font-face()等文件外链
脚本请求: js发起的ajax请求、dom和js对象的跨域操作等
由于浏览器的同源策略限制,不允许跨域请求;但是页面中的 script、img、iframe标签是例外,不受同源策略限制。
当浏览器想目标URI发送Ajax请求时,只要当前URL和目标URL不同源,则产生跨域,成为跨域请求。
解决跨域的方法:
1、跨域资源共享CORS
普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。
需注意的是:由于同源策略的限制,所读取的cookie为跨域请求接口所在域的cookie,而非当前页。如果想实现当前页cookie的写入,可参考下文:七、nginx反向代理中设置proxy_cookie_domain 和 八、NodeJs中间件代理中cookieDomainRewrite参数的设置。
目前,所有浏览器都支持该功能(IE8+:IE8/9需要使用XDomainRequest对象来支持CORS)),CORS也已经成为主流的跨域解决方案。
2、JSONP
虽然XMLHttpRequest对象遵循同源政策,但是script标签不一样,它可以通过 src 填上目标地址从而发出 GET 请求,实现跨域请求并拿到响应。这也就是 JSONP 的原理。
通常为了减轻web服务器的负载,我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许,基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信。
JSONP 的原理就是,先在全局注册一个回调函数,定义回调数据的处理;与服务端约定好一个同名回调函数名,服务端接收到请求后,将返回一段 Javascript,在这段 Javascript 代码中调用了约定好的回调函数,并且将数据作为参数进行传递。当网页接收到这段 Javascript 代码后,就会执行这个回调函数。
步骤: 1).去创建一个script标签 2).script的src属性设置接口地址 3).接口参数,必须要带一个自定义函数名,要不然后台无法返回数据 4).通过定义函数名去接受返回的数据
jsonp缺点:只能实现get一种请求。
3、Nginx代理跨域
是一种高性能的反向代理服务器,可以用来轻松解决跨域问题。
(1) nginx配置解决iconfont跨域
浏览器跨域访问js、css、img等常规静态资源被同源策略许可,但iconfont字体文(eot|otf|ttf|woff|svg)例外,此时可在nginx的静态资源服务器中加入以下配置。
location / {
add_header Access-Control-Allow-Origin *;
}
(2) nginx反向代理接口跨域
跨域原理: 同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。
实现思路:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。
4、document.domain + iframe 跨域
仅限主域相同,子域不同的跨域应用场景。
实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。
5、location.hash + iframe
实现原理: a欲与b跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。
具体实现:A域:a.html -> B域:b.html -> A域:c.html,a与b不同域只能通过hash值单向通信,b与c也不同域也只能单向通信,但c与a同域,所以c可通过parent.parent访问a页面所有对象。
6、window.name + iframe
window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。
总结:通过iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。
7、postMessage 利用h5新特性window.postMessage()
postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
a.) 页面和其打开的新窗口的数据传递
b.) 多窗口之间消息传递
c.) 页面与嵌套的iframe消息传递
d.) 上面三个场景的跨域数据传递
用法:postMessage(data,origin)方法接受两个参数
data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
origin: 协议+主机+端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。
8、nodejs中间件代理跨域
原理大致与nginx相同,都是通过启一个代理服务器,实现数据的转发,也可以通过设置cookieDomainRewrite参数修改响应头中cookie中域名,实现当前域的cookie写入,方便接口登录认证。
9、WebSocket协议跨域
WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现。
原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。
和CORS相比,JSONP 最大的优势在于兼容性好,IE 低版本不能使用 CORS 但可以使用 JSONP,缺点也很明显,请求方法单一,只支持 GET 请求。
讲讲cors,哪些是简单请求?
同源策略,什么地方用到了
iframe有哪些缺点?
iframe会阻塞主页面的Onload事件
搜索引擎的检索程序无法解读这种页面,不利于SEO
iframe和主页面共享连接池,而浏览器对相同域的连接有限制,所以会影响页面的并行加载
使用iframe之前需要考虑这两个缺点。如果需要使用iframe,最好是通过javascript动态给iframe添加src属性值,这样可以绕开以上两个问题
WEB标准以及W3C标准是什么?
- 标签闭合、标签小写、不乱嵌套、使用外链
css和js、结构行为表现的分离
除了script还有哪些标签不受跨域影响?
img link
TCP/IP的五层协议模型 OS的七层协议模型 TCP协议在哪一层?ftp呢?端口号♥ ♥ ♥
HTTP的几种请求
GET方法
POST方法
PUT方法
HEAD方法
DELETE方法
OPTIONS方法
TRACE方法
CONNECT方法
http keep-alive
浏览器中,url中有两个同名的key会怎样
url的编解码方式
VUE
30 道 Vue 面试题,内含详细讲解(涵盖入门到精通,自测 Vue 掌握程度)
说说对Vue的了解
VUE的生命周期?项目用到了什么生命周期?vue数据请求在哪个生命周期?为什么?♥ ♥ ♥
Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模版、挂载 Dom -> 渲染、更新 -> 渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。
beforeCreate阶段:vue实例的挂载元素el和数据对象data都是undefined,还没有初始化。
created阶段:vue实例的数据对象data有了,可以访问里面的数据和方法,未挂载到DOM,el还没有
beforeMount阶段:vue实例的el和data都初始化了,但是挂载之前为虚拟的dom节点
mounted阶段:vue实例挂载到真实DOM上,就可以通过DOM获取DOM节点
beforeUpdate阶段:响应式数据更新时调用,发生在虚拟DOM打补丁之前,适合在更新之前访问现有的DOM,比如手动移除已添加的事件监听器
updated阶段:虚拟DOM重新渲染和打补丁之后调用,组成新的DOM已经更新,避免在这个钩子函数中操作数据,防止死循环
beforeDestroy阶段:实例销毁前调用,实例还可以用,this能获取到实例,常用于销毁定时器,解绑事件
destroyed阶段:实例销毁后调用,调用后所有事件监听器会被移除,所有的子实例都会被销毁
vue操作dom在哪个生命周期?
在钩子函数 mounted 被调用前,Vue 已经将编译好的模板挂载到页面上,所以在 mounted 中可以访问操作 DOM。vue 具体的生命周期示意图可以参见如下,理解了整个生命周期各个阶段的操作,关于生命周期相关的面试题就难不倒你了。
Vue 的父组件和子组件生命周期钩子函数执行顺序?
Vue 的父组件和子组件生命周期钩子函数执行顺序可以归类为以下 4 部分:
-
加载渲染过程
父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted
-
子组件更新过程
父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
-
父组件更新过程
父 beforeUpdate -> 父 updated
-
销毁过程
父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
在哪个生命周期内调用异步请求?
可以在钩子函数 created、beforeMount、mounted 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。但是本人推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:
- 能更快获取到服务端数据,减少页面 loading 时间;
- ssr 不支持 beforeMount 、mounted 钩子函数,所以放在 created 中有助于一致性;
computed和watch的区别
computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;
watch: 更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;
运用场景:
当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;
当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
说一下对MVVM的理解
MVVM即Model-View-ViewModel,将其中的 View 的状态和行为抽象化,让我们可以将UI和业务逻辑分开。MVVM的优点是低耦合、可重用性、独立开发。
vue双向数据绑定原理 ,发布订阅者模式♥ ♥ ♥ ♥ ♥ ♥
Vue 主要通过以下 4 个步骤来实现数据双向绑定的:
1、实现一个监听器 Observer:对数据对象进行遍历,包括子属性对象的属性,利用 Object.defineProperty() 对属性都加上 setter 和 getter。这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化。
2、实现一个解析器 Compile:解析 Vue 模板指令,将模板中的变量都替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,调用更新函数进行数据更新。
3、实现一个订阅者 Watcher:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁 ,主要的任务是订阅 Observer 中的属性值变化的消息,当收到属性值变化的消息时,触发解析器 Compile 中对应的更新函数。
4、实现一个订阅器 Dep:订阅器采用 发布-订阅 设计模式,用来收集订阅者 Watcher,对监听器 Observer 和 订阅者 Watcher 进行统一管理。
v-model的原理
如果视图更新会更新数据吗?怎么更新?
Vue 框架怎么实现对象和数组的监听?
通过 Object.defineProperty() 对数据进行劫持,但是 Object.defineProperty() 只能对属性进行数据劫持,不能对整个对象进行劫持,同理无法对数组进行劫持,但是我们在使用 Vue 框架中都知道,Vue 能检测到对象和数组(部分方法的操作)的变化,那它是怎么实现的呢?我们查看相关代码如下:
Proxy 与 Object.defineProperty()
vue的响应式原理?vue响应式布局 ♥
vue采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty劫持data属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
vue2 和vue3有哪些更新?♥ ♥
Object.defineProperty 只是对对象的属性进行劫持、 无法监听新增属性和删除属性、 深层对象的劫持需要一次性递归、 劫持数组时需要重写覆盖部分 Array.prototype 原生方法,Proxy: 真正的对对象本身进行劫持、 可以监听到对象新增删除属性、 只在 getter 时才对对象的下一层进行劫持(优化了性能)、 能正确监听原生数组方法
Vue 3.0 正走在发布的路上,Vue 3.0 的目标是让 Vue 核心变得更小、更快、更强大,因此 Vue 3.0 增加以下这些新特性:
(1)监测机制的改变
3.0 将带来基于代理 Proxy 的 observer 实现,提供全语言覆盖的反应性跟踪。这消除了 Vue 2 当中基于 Object.defineProperty 的实现所存在的很多限制:
只能监测属性,不能监测对象
检测属性的添加和删除;
检测数组索引和长度的变更;
支持 Map、Set、WeakMap 和 WeakSet。
新的 observer 还提供了以下特性:
1、用于创建 observable 的公开 API。这为中小规模场景提供了简单轻量级的跨组件状态管理解决方案。
2、默认采用惰性观察。在 2.x 中,不管反应式数据有多大,都会在启动时被观察到。如果你的数据集很大,这可能会在应用启动时带来明显的开销。在 3.x 中,只观察用于渲染应用程序最初可见部分的数据。
3、更精确的变更通知。在 2.x 中,通过 Vue.set 强制添加新属性将导致依赖于该对象的 watcher 收到变更通知。在 3.x 中,只有依赖于特定属性的 watcher 才会收到通知。
4、不可变的 observable:我们可以创建值的“不可变”版本(即使是嵌套属性),除非系统在内部暂时将其“解禁”。这个机制可用于冻结 prop 传递或 Vuex 状态树以外的变化。
5、更好的调试功能:我们可以使用新的 renderTracked 和 renderTriggered 钩子精确地跟踪组件在什么时候以及为什么重新渲染。
(2)模板
模板方面没有大的变更,只改了作用域插槽,2.x 的机制导致作用域插槽变了,父组件会重新渲染,而 3.0 把作用域插槽改成了函数的方式,这样只会影响子组件的重新渲染,提升了渲染的性能。
同时,对于 render 函数的方面,vue3.0 也会进行一系列更改来方便习惯直接使用 api 来生成 vdom 。
(3)对象式的组件声明方式
vue2.x 中的组件是通过声明的方式传入一系列 option,和 TypeScript 的结合需要通过一些装饰器的方式来做,虽然能实现功能,但是比较麻烦。3.0 修改了组件的声明方式,改成了类式的写法,这样使得和 TypeScript 的结合变得很容易。
此外,vue 的源码也改用了 TypeScript 来写。其实当代码的功能复杂之后,必须有一个静态类型系统来做一些辅助管理。现在 vue3.0 也全面改用 TypeScript 来重写了,更是使得对外暴露的 api 更容易结合 TypeScript。静态类型系统对于复杂代码的维护确实很有必要。
(4)其它方面的更改
vue3.0 的改变是全面的,上面只涉及到主要的 3 个方面,还有一些其他的更改:
支持自定义渲染器,从而使得 weex 可以通过自定义渲染器的方式来扩展,而不是直接 fork 源码来改的方式。
支持 Fragment(多个根节点)和 Protal(在 dom 其他部分渲染组建内容)组件,针对一些特殊的场景做了处理。
基于 treeshaking 优化,提供了更多的内置功能。
作者:我是你的超级英雄
链接:https://juejin.cn/post/6844903918753808398
v-if 和 v-show 区别及应用场景,在页面第一次渲染时,哪个比较快 ♥ ♥ ♥ ♥
v-if 是真正的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的 “display” 属性进行切换。
所以,v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。
vue中@和:是什么的缩写
@是v-on : 是v-bind
v-for中key值的作用 ♥
vue状态提升
vue与react区别 ♥ ♥
vue组件间传值的方法,子组件间传值,兄弟组件如何实现传值?eventBus
-
父组件给子组件传值通过props
-
子组件给父组件传值通过$emit触发回调
-
兄弟组件通信,通过实例一个vue实例eventBus作为媒介,要相互通信的兄弟组件之中,都引入eventBus
Vue 组件间通信只要指以下 3 类通信:父子组件通信、隔代组件通信、兄弟组件通信,下面我们分别介绍每种通信方式且会说明此种方法可适用于哪类组件间通信。
虚拟DOM,数据的更新,最后是如何反映到真实dom树上的 ♥
vuex原理, 为什么要使用vuex? 怎么用的,适用的项目♥ ♥ ♥
页面通过mapAction异步提交事件到action。action通过commit把对应参数同步提交到mutation。 mutation会修改state中对于的值。 最后通过getter把对应值跑出去,在页面的计算属性中 通过mapGetter来动态获取state中的值
mutation是同步的吗?可以直接改state吗?
是
介绍一下vue-router路由传参
vue的路由懒加载是怎么实现的?♥
图片的懒加载和预加载
对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片先不做加载, 等到滚动到可视区域后再去加载。这样对于页面加载性能上会有很大的提升,也提高了用户体验。我们在项目中使用 Vue 的 vue-lazyload 插件:
在 vue 文件中将 img 标签的 src 属性直接改为 v-lazy ,从而将图片显示方式更改为懒加载显示:
前端路由是怎么实现的?有哪些方式? ♥
hash模式
即地址栏URL中的#符号,它的特点在于:hash 虽然出现URL中,但不会被包含在HTTP请求中,对后端完全没有影响,不需要后台进行配置,因此改变hash不会重新加载页面。
history模式
利用了HTML5 History Interface 中新增的pushState() 和replaceState() 方法(需要特定浏览器支持)。history模式改变了路由地址,因为需要后台配置地址。
abstract
支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式.
vue过滤器用过吗?
组件中 data 为什么是一个函数?
因为组件是用来复用的,且 JS 里对象是引用关系,如果组件中 data 是一个对象,那么这样作用域没有隔离,子组件中的 data 属性值会相互影响,如果组件中 data 选项是一个函数,那么每个实例可以维护一份被返回对象的独立的拷贝,组件实例之间的 data 属性值不会互相影响;而 new Vue 的实例,是不会被复用的,因此不存在引用对象的问题。
说一下vue的常用指令
diff算法
虚拟DOM
(1)深度优先遍历,记录差异
在实际的代码中,会对新旧两棵树进行一个深度优先的遍历,这样每个节点都会有一个唯一的标记:
在深度优先遍历的时候,每遍历到一个节点就把该节点和新的的树进行对比。如果有差异的话就记录到一个对象里面。
(2)差异类型
DOM 操作导致的差异类型包括以下几种:
节点替换:节点改变了,例如将上面的 div 换成 h1;
顺序互换:移动、删除、新增子节点,例如上面 div 的子节点,把 p 和 ul 顺序互换;
属性更改:修改了节点的属性,例如把上面 li 的 class 样式类删除;
文本改变:改变文本节点的文本内容,例如将上面 p 节点的文本内容更改为 “Real Dom”;
(3)列表对比算法
•子节点的对比算法,例如 p, ul, div 的顺序换成了 div, p, ul。这个该怎么对比?如果按照同层级进行顺序对比的话,它们都会被替换掉。如 p 和 div 的 tagName 不同,p 会被 div 所替代。最终,三个节点都会被替换,这样 DOM 开销就非常大。而实际上是不需要替换节点,而只需要经过节点移动就可以达到,我们只需知道怎么进行移动。
•将这个问题抽象出来其实就是字符串的最小编辑距离问题(Edition Distance),最常见的解决方法是 Levenshtein Distance , Levenshtein Distance 是一个度量两个字符序列之间差异的字符串度量标准,两个单词之间的 Levenshtein Distance 是将一个单词转换为另一个单词所需的单字符编辑(插入、删除或替换)的最小数量。Levenshtein Distance 是1965年由苏联数学家 Vladimir Levenshtein 发明的。Levenshtein Distance 也被称为编辑距离(Edit Distance),通过动态规划求解,时间复杂度为 O(M*N)。
我们查看输出的两个虚拟 DOM 对象之间的差异对象如下图所示,我们能通过差异对象得到,两个虚拟 DOM 对象之间进行了哪些变化,从而根据这个差异对象(patches)更改原先的真实 DOM 结构,从而将页面的 DOM 结构进行更改。
nextTick的实现
mixin、slot
具名插槽,插槽作用域
keep-alive ❤❤❤
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染 ,其有以下特性:
- 一般结合路由和动态组件一起使用,用于缓存组件;
- 提供 include 和 exclude 属性,两者都支持字符串或正则表达式, include 表示只有名称匹配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高;
- 对应两个钩子函数 activated 和 deactivated ,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated。
Vue 怎么用 vm.$set() 解决对象新增属性不能响应的问题 ?
vue怎样编译的
vue框架的优点
vue如何实现轮播图插件? ♥
proxy,可以监听嵌套对象的变化吗?
vue组件中,如何等待接口获取完数据后输出结果
vue底层扩展能力,插件机制是什么
插件体现的方式,挂载的流程
自己开发一个工具,怎么考虑自己工具的扩展性
js异步处理,哪几种
回调函数
事件监听
发布/订阅
promise对象
async/await
组件封装是怎么做到的,封装了哪些组件
设计组件如何保证组件的复用性,比如说一个form表单
组件能不能用JSON来实现调用
SPA单页面,优缺点
SPA( single-page application )仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现 HTML 内容的变换,UI 与用户的交互,避免页面的重新加载。
优点:
用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
基于上面一点,SPA 相对对服务器压力小;
前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;
缺点:
初次加载耗时多:为实现单页 Web 应用功能及显示效果,需要在加载页面的时候将 JavaScript、CSS 统一加载,部分页面按需加载;
前进后退路由管理:由于单页应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理;
SEO 难度较大:由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上其有着天然的弱势。
移动端
移动端适配问题 ♥
响应式布局中的rem em 的区别,哪个是根据根元素变化的
移动端像素和台式机不一样怎么办?
用视口,使比例为1:1
遇到过响应式布局中1px的border问题吗? 查查论坛
项目
说说印象最深刻的一个项目
做过团队协作的项目吗
希望以后做前端哪一块?
对前端的认识,为什么选择前端,如何看待前端这个岗位?
如何部署项目,实现项目?
对项目中的各个模块如何看待,为何要分这么多模块
项目中遇到的难点,如何解决?♥ ♥
职业规划,前端的发展
怎么学习的前端,路线,规划
项目中的收获
开发过程中有哪些安全相关的问题,用token不用cookie ♥ ♥
未知归类
性能优化考虑到了什么?
首屏加载慢怎么优化
如何实现图片懒加载?
第一打开显示会监听页面区域吗?
前端性能优化
webpack,如何配置 ♥
url到网页展示的过程 ♥
前端打包工具是什么?vue项目用的是什么打包工具?为什么要使用打包工具?
设计模式 ♥ ♥ ,单例模式
路由模式,hash如何实现回退等功能,history模式
了解前后端分离吗,说说认识,有什么优点
在调用接口的页面中,刚进来时产生白屏可能是什么原因?
mysql数据库的隔离级别?mysql的隔离级别是如何实现的??mysql里边有哪几种索引?答的是组合索引、唯一索引、聚集索引、非聚集索引?索引失效的情况?where子句里如果只对A进行大小判断(非like),并且索引只有A,一定会走索引么?
数据库 having
数据库 索引
计算机基础
进程和线程的区别? ♥ ♥
进程通信
死锁,如何防止死锁
场景题
如何实现一个输入框,能及时判断用户输入的数据的合法性,用什么实现?
怎么在一个app中嵌入一个h5页面
一个九宫格切换的时候,引起抖动怎么解决
给一个列表每一行加一个删除按钮,有什么办法
回答:利用事件委托,给每一个标签添加方法,通过循环用js操作dom添加事件
循环方法,最后只能绑定给最后一个,怎么解决 回答了利用闭包,立即执行函数
问还有没有别的办法,答在循环是可以用let声明(小哥哥说就是想让说let)
两行代码实现数组各元素+1;
数组中最大值和最小值的差值
给个字符串,拿到其中的数字,返回数字数组,匹配字符串中的所有数字,包括科学计数法、小数、分数和负数。
const str = '这是一篇文章:加快递费3.22X10^5,就开始的经费3673降低开jvjsldfjXDJKFLD发洛索洛芬2/3,是杜绝浪费0.12345,晋升的了客服-2344'
// ['3.22X10^5',3673,'2/3',0.12345,-2344]
var a = 'My name is zhang'; 对每个单词开头字母实现大写
\