前端三剑客(html、css、js)面试题

Html/Css

行内元素/块级元素,非替换元素/替换元素

  1. 块级元素,会独占一行,默认情况下,其宽度自动填满其父元素宽度。块级元素可以设置width,height属性,即使设置了宽度,仍然是独占一行。可以设置margin和padding属性。块级元素对应于display:block。块级元素可以包含块级元素和行内元素。
  2. 行内元素,不会独占一行,相邻的行内元素会排列在同一行里,直到一行排不下,才会换行。行内元素设置width,height属性都无效,它的长度高度主要根据内容决定。行内元素的margin和padding在水平方向会产生边距效果,但竖直方向的却不会产生边距效果。行内元素只能包含行内元素
  3. 替换元素,浏览器根据元素的标签和属性,来决定元素的具体显示内容。例如浏览器会根据 <img>标签的 src 属性的值来读取图片信息并显示出来,而如果查看 HTML 代码,则看不到图片的实际内容;又例如根据 <input>标签的 type 属性来决定是显示输入框,还是单选按钮等。
    <img> 、<input>、<textarea> 、<select> 、<object> 都是替换元素。
  4. 不可替换元素,HTML 的大多数元素是不可替换元素,即其内容直接表现给用户端(例如浏览器)。例如:<p>段落的内容</p>是一个不可替换元素,文字「段落的内容」全被显示。

<img>标签的title和alt属性

  alt属性和title属性的区别是前者是在图片无法加载的时候才会显示的其值,而title是在图片正常加载鼠标划上去显示的值,虽然alt也有后者的功能,但只是在低版本的ie浏览器才支持,高版本及标准浏览器不支持这个功能了。

DOCTYPE 标签

  <!DOCTYPE> 声明必须位于HTML5文档中的第一行。该标签告知浏览器html文档所使用的规范。doctype 声明不属于 HTML 标签。严格模式的排版和 JS 运作模式是以该浏览器支持的最高标准运行。DOCTYPE不存在或格式不正确会导致文档以混杂模式呈现。在混杂模式中,页面以宽松的向后兼容的方式显示。模拟老式浏览器的行为以防止站点无法工作。

link 和 @import

  1. link属于XHTML标签,除了加载CSS外,还能用于定义RSS,定义rel连接属性等作用;而@import是CSS提供的,只能用于加载 CSS。
  2. 加载页面时,link标签引入的 CSS 被同时加载;@import引入的 CSS 将在页面加载完毕后被加载。
  3. @import 是 CSS2.1 提出的,只在 IE5 以上才能被识别,而 link 是 XHTML 标签,无兼容问题。
  4. link 支持使用 JS 控制 DOM 去改变样式,而 @import 不支持。link最大限度支持并行下载,@import过多嵌套导致串行下载,会使文档样式短暂失效。

script标签的defer和async

  script 标签有2个属性 async(异步) 和 defer(推迟)。
9. async:异步加载,不确定何时会加载好;页面加载时,带有 async 的脚本也同时加载,加载完成后会立即执行,如果有一些需要操作 DOM 的脚本加载比较快时,这样会造成 DOM 还没有加载好,脚本就进行操作,会造成错误。
10. defer:页面加载时,带有defer的脚本也同时加载,加载后会等待页面加载好后,才执行。

实现元素水平垂直居中的方法

  1. 利用定位+margin:auto;
  2. 利用定位+margin:负值;
  3. 利用定位+transform;
  4. table布局;
  5. flex布局;
  6. grid布局;
iframe

  iframe元素会创建包含另外一个文档的内联框架(即行内框架)。<iframe>标签用于指定内联框架。内联框架用于向网页中引入另一个网页。

<iframe  src=“hello.html”  width=“200px”  height=“400px” name="ifra">
</iframe>

<iframe>标签常用属性:

  1. src属性:是在该内联框架中指定一个外部的页面地址;
  2. name属性:是设置iframe的名字

优点:用来加载速度较慢的内容(如广告);可以使脚本并行下载;可以实现跨子域通信;
缺点:iframe标签会阻塞页面的的加载,会阻塞主页面的onload事件;无法被一些搜索引擎索识别;会产生很多页面,不容易管理;iframe的创建比一般的DOM元素慢了1-2个数量级。

BFC

  即块级格式化上下文,它是页面中的一块渲染区域,并且有一套属于自己的渲染规则:

  1. 内部的盒子会在垂直方向上一个接一个的放置;
  2. 对于同一个BFC的俩个相邻盒子的margin会发生重叠,与方向无关。
  3. 每个元素的左外边距与包含块的左边界相接触,即使浮动元素也是如此;
  4. BFC的区域不会与float的元素区域重叠
  5. 计算BFC的高度时,浮动子元素也参与计算;
  6. BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素

触发BFC的条件包含不限于:
(1)根元素,即HTML元素;
(2)浮动元素:float值为left、right;
(3)overflow值不为 visible,为 auto、scroll、hidden;
(4)display的值为inline-block、flex、inline-flex、grid、inline-grid等;
(5)position的值为absolute或fixed;
BFC应用在以下场景:防止margin重叠(塌陷);清除内部浮动;自适应多栏布局

清除浮动的方法

(1)给父级盒子添加高度
(2)额外标签法,在浮动元素末尾添加一个空的块级标签。原理:clear:both的作用是不允许周围有浮动现象,所以就可以达到清除浮动的效果。
(3)给父级添加 overflow 属性。overflow:hidden本身的意思是溢出的元素隐藏显示。
(4)给父级添加after伪元素。利用after伪元素定义一个clearfix类,浮动元素的父级元素调用此类可以实现清除浮动的效果。这个方式的原理和额外标签法的方式异曲同工,只是向浮动元素的后面添加了一个块级元素。

position属性

(1)position: relative;相对定位,不会使元素脱离文档流,不影响其他元素的偏移,因此会在此元素未添加定位时所在位置留下空白。提升层级(用z-index样式的值可以改变一个定位元素的层级关系,从而改变元素的覆盖关系,值越大越在上面,z-index只能在position属性值为relative或absolute或fixed的元素上有效。)
(2)position: absolute 绝对定位,使元素完全脱离文档流(在文档流中不再占位),使内联元素在设置宽高的时候支持宽高,使区块元素在未设置宽度时由内容撑开宽度,相对于最近一个有定位的父元素偏移(若其父元素没有定位则逐层上找,直到document——页面文档对象),相对定位一般配合绝对定位使用,提升层级
(3)position: fixed 固定定位,生成固定定位的元素在浏览器中不占位置,相对于浏览器窗口进行定位,不以body为依据。
(4)position:static 默认布局。元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)
(5)position:sticky 粘性定位,该定位基于用户滚动的位置。它的行为就像 position:relative; 而当页面滚动超出目标区域时,它的表现就像 position:fixed;它会固定在目标位置。

CSS隐藏元素的方式

通过css实现隐藏元素方法有如下:

方法一:display:none

.conceal {display:none} //display:none是通常最实用的隐藏元素的方法
此元素原本所占据的位置,会被其他元素占据,也就是说它会导致浏览器的重排和重绘。消失后,自身绑定的事件不会触发,也不会有过渡效果。特点:元素不可见,不占据空间,无法响应点击事件

方法二:visibility:hidden

visibility:hidden从页面上来看仅仅是隐藏该元素,DOM结果依然会存在,只是处于一个不可见的状态。不会发生重排,但是会发生重绘。特点:元素不可见,占据空间,无法响应点击事件。
.conceal {visibility:hidden }

方法三: opacity:0

opacity属性表示元素的透明度,将元素的透明度设置为0之后,元素也是可以达到隐藏效果。不会引发重排,一般情况下也会引发重绘。注意:其子元素不能设置opacity来达到显示的效果。特点:改变元素透明度,元素不可见,占据页面空间,可以响应点击事件。
.conceal {opacity:0}

方法四:设置height、width模型属性为0

要用这种方法实现隐藏需将元素的margin、border、padding、height和width等影响元素盒模型的属性设置成0,如果元素内有子元素的内容,还要设置其overflow:hidden 来隐藏子元素。元素不可见,不占据空间,无法响应点击事件
.conceal {margin:0;border:0;padding:0;height:0;width:0;overflow:hidden;}

方法五:position:absolute

元素不可见,不影响布局
.conceal { position: absolute;top: -9999px;left: -9999px;}

方法六:clip-path

clip-path 通过裁剪的形式,元素不可见,占据空间,无法响应点击事件
.conceal {clip-path: polygon(0px 0px,0px 0px,0px 0px,0px 0px);}

页面渲染的流程

  解析html绘制DOM树,解析css绘制CSS树,把DOM和CSSOM组合生成render tree(渲染树),在渲染树的基础上进行布局,分析每个节点的几何结构,把每个节点绘制到屏幕上(painting)。

重排和重绘

  DOM发生改变的时候触发重排,使DOM重新排列。重绘不一定会重排,但重排一定会发生重绘,重绘和重排都会耗费浏览器的性能,尽量避免。
重绘是在一个元素的外观被改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。
重排就是重新排列(reflow):当渲染树的一部分必须更新并且节点的尺寸发生了变化,浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。

减少重排和重绘

(1)避免一条一条的修改DOM的样式,可以直接修改DOM的className一次性改变属性;
(2)避免把DOM结点的属性值放在一个循环里当成循环里的变量;
(3)给动画的HTML元素使用fixed或absolute的position,那么修改他们的css是不会重排;
(4)避免在大量元素上使用:hover;
(5)分离读写操作;(6)避免使用Table布局;(7)避免设置多层内联样式;(8)避免在布局信息改变时查询布局信息;

CSS Sprites

  CSS Sprites是一种网页图片应用处理方式。它允许你将一个页面涉及到的所有零星图片都包含到一张大图中去。利用CSS的“background-image”,“background- repeat”,“background-position”的组合进行背景定位,background-position可以用数字精确的定位出背景图片的位置。利用CSS Sprites能很好地减少网页的http请求,从而大大的提高页面的性能,这也是CSS Sprites最大的优点;CSS Sprites能减少图片的字节,曾经比较过多次3张图片合并成1张图片的字节总是小于这3张图片的字节总和。解决了网页设计师在图片命名上的困扰,只需对一张集合的图片命名就可以了,从而提高了网页的制作效率。维护起来更加方便。

px rem em

  px,表示像素,所谓像素就是呈现在我们显示器上的一个个小点,每个像素点都是大小等同的,所以像素作为计量单位被分在了绝对长度单位中。一旦设置了就无法因为适应页面大小而改变。
  em是相对长度单位。相对于当前对象内文本的字体尺寸。如当前对行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸(1em=16px)。
  rem是相对于根元素。总之em相对于父元素,rem相对于根元素。
vw,就是根据窗口的宽度,分成100等份,100vw就表示满宽,50vw就表示一半宽。同理,vh则为窗口的高度

浏览器内核

Wekbit:Apple的Safari, Google的Chrome。
Gecko:Firefox便是使用的Gecko 内核。Gecko内核是开源的,最大优势是可以跨平台。
Trident内核:微软的IE系列。搜狗浏览器是双核的,双核并不是指一个页面由2个内核同时处理,而是所有网页由webkit内核处理,只有银行网站用IE内核。
Presto内核:代表浏览器是Opera浏览器(中文译为“欧朋浏览器”),Presto 内核是世界公认最快的渲染速度的引擎,但是在 2013 年之后,Open宣布加入谷歌阵营,弃用了该内核。
Blink内核:由谷歌和 Opera 开发,2013 年4月发布,现在 Chrome 内核是Blink。

JavaScript

JavaScript的数据类型

基本数据类型:Number、String、Boolean、Null、Undefined、Symbol、bigInt
引用数据类型:object、Array、Date、Function、RegExp

变量和函数声明的提升

在js中变量和函数的声明会提升到最顶部执行,函数的提升高于变量的提升。函数内部如果用 var 声明了相同名称的外部变量,函数将不再向上寻找。匿名函数不会提升。

判断变量的类型

typeof:判断基本数据类型
instanceof:判断引用数据类型,判断一个实例是否属于某种类型
使用constructor判断变量的类型
使用Object.prototype.toString.call判断变量的类型
使用jquery中$.type判断变量的类型。

数据类型转换

其他数据类型转换为数字型
方法一:Number()
  1. 空字符串转为0,其他任何非有效数字字符都是NaN
    Number('') -> 0 Number('12c') -> NaN
  2. 布尔值转换为数字:true -> 1 , false -> 0
  3. null -> 0 , undefined -> NaN
  4. Symbol无法转换为数字,会报错:Uncaught TypeError: Cannot convert a Symbol value to a number
  5. BigInt去除’n’(超过安全数字的,会按照科学计数法处理) Number(10n) -> 10
方法二:parseInt([val],[radix])
  1. parseInt([val],[radix])
    a. [val]值必须是一个字符串,如果不是先隐式转换为字符串【通过String([val])转换】
    b. [radix]进制
    –如果不写,或者写0:默认是10进制,如果字符串是以0x开始的,默认是16进制
    –有效范围:2~36之间,如果不在这个区间,结果直接是NaN
    从字符串左侧的第一个字符开始寻找,查找出符合[radix]进制的值【遇到不符合的就结束查找,不论后面是否还有符合的】
    parseInt(‘12px13’,2) -> 1
    parseInt(‘10102px13’,2) -> 1010【二进制】 ->10【十进制】
    方法三:parseFloat([val])
    (1) 转换规则如下
    a. [val]必须是一个字符串,如果不是,就要隐式转换为字符串
    b. 然后从字符串左侧的第一个字符串开始寻找,把找到的有效数字字符最后转换为数字【一个都没找到就是NaN】
    c. 遇到一个非有效数字字符,不论后面是否是有效数字字符,都不在查找了
    d. parseFloat可以多识别一个小数点
    例题
    let arr = [27.2,0,‘0013’,‘14px’,123]
    arr = arr.map(parseInt)
    console.log(arr) //[27,NaN,1,1,27]
    // arr.map((item,index){return item*10})方法:迭代数组的每一项,并对其进行修改(原始数组不变,返回新数组)
    // arr.map(parseInt)相当于把parseInt方法作为参数,然后原数组中的item和index作为parseInt方法的参数
    // parseInt(27.2,0) -> parseInt(‘27.2’,10) -> 27【十进制】
    // parseInt(0,1) -> NaN
    // parseInt(‘0013’,2) -> 001【二进制】 -> 1【十进制】
    // parseInt(‘14px’,3) -> 1【3进制】 -> 1【十进制】
    // parseInt(123,4) -> 123【4进制】 -> 27【十进制】
    // parseInt(0013,2) -> parseInt(11,2) -> parseInt(‘11’,2) ->11【二进制】-> 3【十进制】 【先将0013按照8进制转为10进制的数字11】
    // JS遇到以0开始的“数字”,会默认将其按照8进制转为10进制,然后在进行其他操作
  2. 其他数据类型转换为字符串
    方法一:默认使用String([val])方法
    (1) 若val是一个原始值,则转换结果直接包裹括号即可。特殊情况 String({}) //‘[object Object]’
    (2) 若val是一个对象,转换规则如下
    a. 先调用对象的Symbol.toPrimitive方法,
    b. 如果没有Symbol.toPrimitive方法,在调用对象的indexOf,获取原始值
    【每个对象都有indexOf方法,即便它本身没有,但可以通过原型链访问到Object的原型上的indexOf方法】
    【数组的原始值还是数组】
    c. 如果获取的原始值不是基本数据类型,则调用对象的toString方法将其转换为字符串
    方法二:"+"出现字符串拼接的情况
    (1) "+"两边,一边是字符串
    (2) "+"两边,一边是对象
    (3) "+"出现在值的左侧,除了字符串拼接的情况,而且该值会转换为数字
    let i =‘10’
    console.log(+i) //10
    注意:String([val])和val.toString()的结果不一样
    (1) String([val])的结果除了是字符串外,也可以是别的类型;val.toString()的结果只能是字符串
  3. 其他数据类型转换为布尔值
    除0、NaN、空字符串、null、undefined返回的值是false外,其余都是true
  4. ==比较时的相互转换规则
    ==:两边数据类型不同,需要先转换为相同的类型,然后在进行比较
    (1) 对象==字符串,对象转字符串【Symbol.toPrimitive -> valueOf -> toString】
    (2) null == undefined -> true null/undefined和其他任何值都不相同
    null===undefined -> false
    (3) 对象==对象 比较的是内存地址,地址相同则相等
    (4) NaN !==NaN true NaN==NaN false Object.is(NaN,NaN) true
    (5) 除了以上情况,只要两边类型不一致,剩下的都是转换为数字,然后在进行比较
    console.log([] == false) //true 两边都转换为数字
    console.log(![] ==false) //true 先处理![] -> false false == false -> true
    “===”: 如果两边类型不同,直接返回false,不会发生数据类型转换

DOM事件流和事件委托

  DOM事件流包括三个阶段:捕获阶段、目标阶段、冒泡阶段。
首先发生的是事件捕获,为截获事件提供了机会。然后是实际的目标接收到事件。最后一个是冒泡阶段,在这个阶段对事件做出响应。事件发生时会在元素节点之间按照特定的顺序传播,这个传播的过程就是DOM事件流。简单的说:事件的传播过程即DOM事件流

提高内存和性能 – 事件委托

  对 “事件处理程序过多” 问题的解决方案就是事件委托。事件委托指的是,不在事件的发生地(直接 dom)上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判断事件发生元素 DOM 的类型,来做出不同的响应。
  事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一项类型的所有事件。例如,click事件会一直冒泡到window层次。也就是说,我们可以为整个页面指定一个onclick事件,而不必给每个可单击的元素分别添加事件
  举例:最经典的就是 ul 和 li 标签的事件监听,比如我们在添加事件时候,采用事件委托机制,不会在 li 标签上直接添加,而是在 ul 父元素上添加。 好处:比较合适动态元素的绑定,新添加的子元素也会有监听函数,也可以有事件触发机制。

Cookie/storage

都是保存在浏览器端,并且是同源的

1、cookie本身用于客户端和服务端通信,但是它有本地存储的功能,于是就被“借用”。

cookie用于存储的缺点:①存储量太小,只有 4kb ②所有 http请求都带着,会影响获取资源的效率
③api简单,需要封装才能用 document.cookie。
Cookie的主要作用:
(1)保存用户登录状态。例如将用户 id 存储于一个 cookie 内,这样当用户下次访问该页面时就不需要重新登录了。
(2)cookie 还可以设置过期时间,当超过时间期限后,cookie 就会自动消失。因此,系统往往可以提示用户保持登录状态的时间:常见选项有一个月、三个月、一年等。
(3)跟踪用户行为。例如一个天气预报网站,能够根据用户选择的地区显示当地的天气情况。 如果每次都需要选择所在地是烦琐的,当利用了 cookie 后就会显得很人性化了,系统能够记住上一次访问的地区,当下次再打开该页面时,它就会自动显示上次用户所在地区的天气情况。因为一切都是在后台完成,所以这样的页面就像为某个用户所定制的一样,使用起来非常方便定制页面。

2、localStorage,sesseionStorage

html5专门为存储而设计,最大容量5M。api简单易用。lcoalStorage.setItem(key,value);localStoragegetItem(key);
sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage仅仅是会话级别的存储。而localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。

map与forEach的区别

(1)forEach()方法不会返回执行结果,而是undefined
(2)map()方法会得到一个新的数组并返回
(3)同样的一组数组,map()的执行速度优于 forEach()(map() 底层做了深度优化)
forEach() 适合于并不打算改变数据的时候,而只是想用数据做一些事情(比如存入数据库)
let arr = [‘a’, ‘b’, ‘c’, ‘d’];
arr.forEach((val) => {console.log(val)}); // 依次打印出 a,b,c,d
map() 适用于要改变数据值的时候,它更快,而且返回一个新的数组
let arr = [1, 2, 3, 4, 5];
let arr2 = arr.map(num => num * 2).filter(num => num > 5); // arr2 = [6, 8, 10]
forEach 方法,是最基本的方法,就是遍历与循环,默认有 3 个传参:分别是遍历的数组内容 item、数组索引 index、和当前遍历数组 Array
map 方法,基本用法与 forEach 一致,但是不同的,它会返回一个新的数组,所以 callback需要有 return 值,如果没有,会返回 undefined。

数组和对象的常见方法

前五个迭代数组的方法语法都一样,都不会改变原数组
Array.map();Array.forEach()
Array.filter():此方法类似于筛选向方法中传入一个判断条件,将满足条件的值变成一个新的数组返回。
Array.every():此方法是将所有元素进行判断返回一个布尔值,如果所有元素都满足判断条件的话,则返回true,如果不满足就返回 false。遍历数组每一项,若全部为true,才返回true ,否则返回false
Array.some():此方法和every类似,唯一区别就是some遍历数组中的每一项,若其中一项为true,则返回值是true,every遍历数组每一项,若全部为true,才返回true ,否则返回false。
Array.reduce():reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组。可以用来写求和求积、最大值、最小值。
Array.push():此方法用来向数组末尾添加一个或多个元素,返回新增后数组的长度。
Array.pop():此方法删除数组中的最后一位元素,并返回删除的元素。
Array.shift():此方法删除数组中的第一个元素。
Array.unshift():此方法向数组前添加一个或多个元素,并返回新增后数组的长度。
Array.isArray():此方法是用来判断一个对象是不是数组,是的话返回true,不是返回false。
Array.concat():此方法是一个可以将多个数组合并成一个数组的方法。不会改变原数组,返回合并之后的数组。
Array.toString():此方法是用来将数组转变为字符串格式。
Array.join():通过指定连接符生成字符串。原数组不变
Array.splice(开始位置, 删除的个数,元素),万能的方法可以实现数组的增、删、改。
Array.slice():此方法返回从原数组中指定开始下标到结束下标之间的项组成的新数组(原数组不变)截取数组。前闭后开
Array.includes():此方法用来判断数组中是否有指定的元素,有的话返回true,没有的话返回false。
Array.indexOf():从数组的开头向后查找,接受两个参数,要查找的项和查找起点的位置索引。
Array.sort():按指定的参数对数组进行排序,返回的值是经过排序后的数组(无参,函数)
Array.fill():此方法用来替换数组中的元素,会改变原数组。
接受三个参数,第一个参数为替换的值,如果只传入一个值会吧数组中的值全部替换。
第二个参数是标记为从第几个位置开始替换,会从标记的位置开始把后面的元素全部替换。
第三个参数是结束时的索引。

对象的方法

1.Object.assign()
此方法用于克隆对象,传入两个参数,第一个参数为原对象,第二个参数为需要克隆的对象。会合并为一个新的对象,改变第一个参数的对象。
2.Object.is()
此方法是用来比较的接受两个参数,第一个参数是需要比较的第一个值,第二个参数是需要比较的第二个值。
返回值:布尔值,如果两个值相同返回true,不相同返回false。
注意,该函数与运算符不同,不会强制转换任何类型,应该更加类似于=,但值得注意的是它会将+0和-0视作不同值
3.Object.keys()
此方法是用来获取对象的key值的。返回一个包含key值的数组。
4.Object.defineProperty()
defineProperty为设置对象的属性的属性特征 value设置属性名,enumerable设置该属性是否可以被枚举。未设置的枚举的属性不能被for in遍历和keys获取。
该方法接受三个参数,第一个参数为要加入属性的对象,第二个参数为属性的key值,第三个参数为一个对象。
5.Object.defineProperties()
可添加多个属性,与Object.defineProperty()对应。
6.Object.isPrototypeOf()
此方法是用来检查一个对象是否存在另一个对象的原型链中。

requestAnimationFrame

  在Web应用中,实现动画效果的方法比较多,Javascript 中可以通过定时器 setTimeout/ setInterval 来实现,css3 可以使用 transition和 animation 来实现,html5 中的 canvas 也可以实现。除此之外,html5 还提供一个专门用于请求动画的API,那就是 requestAnimationFrame。
  setTimeout/ setInterval 的显著缺陷就是设定的时间并不精确,它们只是在设定的时间后将相应任务添加到任务队列中,而任务队列中如果还有前面的任务尚未执行完毕,那么后添加的任务就必须等待,这个等待的时间造成了原本设定的动画时间间隔不准。
  requestAnimationFrame的到来就是解决这个问题的 ,它采用的是系统时间间隔(约16.7ms),使各种网页动画有一个统一的刷新机制,从而节省系统资源,提高系统性能。requestAnimationFrame() 方法告诉浏览器用户希望执行动画并请求浏览器在下一次重绘之前调用指定的函数来更新动画。该方法使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。 特点:
(1)requestAnimationFrame 会把每一帧中的所有 DOM 操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率。
(2)在隐藏或不可见的元素中,requestAnimationFrame 将不会进行重绘或回流,这就意味着更少的 CPU、GPU 和内存使用量
(3)requestAnimationFrame 是由浏览器专门为动画提供的 API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了 CPU 开销。

this指向

  1. 单独使用 this,它指向全局(Global)对象。
  2. 在对象方法中,this 指向调用它所在方法的对象。
  3. 函数使用中,this 指向函数的调用者。
  4. 严格模式下函数是没有绑定到 this 上,这时候 this 是 undefined。
  5. 在 HTML 事件句柄中,this 指向了接收事件的 HTML 元素。
  6. apply 和 call、bind允许切换函数执行的上下文环境(context),可以将 this 引用到任何对象。

作用域链

一、作用域
作用域就是变量和函数生效的区域或集合,即作用域决定了代码区块中变量和其他资源的可见性

  1. 全局作用域
    任何不在函数中或是大括号中声明的变量,都会在全局作用域下,全局作用域下声明的变量可以在程序的任意位置访问。
  2. 函数作用域
    函数作用域也叫局部作用域,如果一个变量是在函数内部声明的,他就在该函数的作用域下面。这些变量只能在函数内部访问,不能在函数以外去访问。
  3. 块级作用域
    ES6引入了let和const关键字,和var关键字不同,在大括号中使用let和const声明的变量存在于块级作用域中。在大括号之外不能访问这些变量。
    二、词法作用域
    词法作用域,又叫静态作用域,变量被创建时就确定好了,而非执行阶段确定的。也就是说我们写好代码时它的作用域就确定了,JavaScript 遵循的就是词法作用域
var a = 2;
function foo(){
    console.log(a)
}
function bar(){
    var a = 3;
    foo();
}
bar();

上述代码变成下图:
由于JavaScript遵循词法作用域,相同层级的 foo 和 bar 就没有办法访问到彼此块作用域中的变量,所以输出2。

三、作用域链

  当在Javascript中访问一个变量的时候,首先Javascript引擎会在当前作用域下去寻找该变量,如果没找到,再到它的上层作用域寻找,以此类推直到找到该变量或是已经到了全局作用域。如果在全局作用域里仍然找不到该变量,它就会在全局范围内隐式声明该变量(非严格模式下)或是直接报错。

let/const/var的区别

(1)块级作用域:块作用域由{ }包括,let和const具有块级作用域,var不存在块级作用域。
(2)变量提升:var存在变量提升,let和const不存在变量提升,即在变量只能在声明之后使用,否在会报错。
(3)给全局添加属性:浏览器的全局对象是window。var声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但是let和const不会。
(4)重复声明:var声明变量时,可以重复声明变量,后声明的同名变量会覆盖之前声明的变量。const和let不允许重复声明变量。
(5)暂时性死区:在使用let、const命令声明变量之前,该变量都是不可用的。这在语法上称为暂时性死区。使用var声明的变量不存在暂时性死区。
(6)初始值设置:在变量声明时,var 和 let 可以不用设置初始值。而const声明变量必须设置初始值。
指针指向: let创建的变量是可以更改指针指向(可以重新赋值)。但const声明的变量是不允许改变指针的指向。

箭头函数

  1. 如果形参只有一个,则小括号可以省略;
  2. 函数体如果只有一条语句,则花括号可以省略,并省略return,函数的返回值为该条语句的执行结果;
  3. 箭头函数 this 指向声明时所在作用域下 this 的值;
  4. 不能作为构造实例化对象;不能使用 arguments 关键字;可以用 Rest 参数代替
  5. 不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数
JavaScript的运行机制

  JavaScript 是一门单线程的语言。单线程就意味着,一次只能执行一个任务,其他任务都需要排队等待。在 HTML5 中提出了 web worker 标准,它提供了一套完整的 API 去允许在主线程以外去执行另一个线程,但是不能访问 DOM。这不意味着 JavaScript 从此拥有了多线程的能力。在 JS中还有着独特执行机制,它将主线程中的任务分为同步任务和异步任务。
  同步任务:是在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务,例如:console.log
  异步任务:不进入主线程、通过事件循环机制处理,在任务队列中注册回调函数最终拿到结果,例如:setTimeout

事件循环

首先我们用一张图来理解事件循环
在这里插入图片描述

  运行机制:所有同步任务在主线程上执行,形成一个执行栈,也就是上图蓝色箭头表示。主线程以外有一个异步任务队列(红色箭头),会等到异步任务返回结果后将它放入任务队列。当主线程中执行栈代码执行完毕,也就是同步任务执行完毕,就会开始读取任务队列代码,再放入执行栈中执行。
  不断地重复上面三步,这就是事件循环。用图形来描绘的话,就是上图中的三个黑色箭头,连成的闭环。也就是说:只要主线程执行栈空了,就会去读取任务队列,这个过程是循环不断的,这种运行机制就叫做事件循环。
  常见的会放入异步任务队列的事件:DOM 事件、Promise、Ajax 请求、setTimeout 和 setlnterval、文件上传

宏任务和微任务

宏任务有:HTML解析、鼠标事件、键盘事件、网络请求、执行主线程js代码和定时器
微任务有:promise.then,DOM 渲染,async,process.nextTick
那它是怎么被执行的呢?
当执行栈中的同步任务执行完毕后,先执行微任务;
微任务队列执行完毕后,会读取宏任务;
执行宏任务的过程中,遇到微任务,再加入微任务队列;
宏任务执行完后,再次读取微任务队列,依次循环;

微任务永远在宏任务执行之前被执行完毕

垃圾回收机制

  JS的垃圾回收机制是为了以防内存泄漏,内存泄漏的含义就是当已经不需要某块内存时这块内存还存在着,没有被释放,导致该内存无法被使用,垃圾回收机制就是间歇的不定期的寻找到不再使用的变量,并释放掉它们所指向的内存。

垃圾回收方式

  通常有两种方式:标记清除(mark and sweep)、引用计数(reference counting)
标记清除
这是JavaScript中最常用的垃圾回收方式。
(1)当变量进入执行环境时(函数中声明变量),就标记这个变量为“进入环境”,当变量离开环境时(函数执行结束),则将其标记为“离开环境”,离开环境之后还有的变量则是需要被删除的变量。
(2)垃圾回收器在运行的时候会给存储在内存中的所有变量都加上标记。
(3)去掉环境中的变量以及被环境中变量引用的变量的标记。
(4)之后再被加上标记的变量即是需要回收的变量(因为环境中的变量已经无法访问到这些变量)
(5)最后,垃圾收集器完成内存清除工作,销毁那些带标记的值,并回收他们所占用的内存空间。
引用计数
  这种方式常常会引起内存泄漏,低版本的IE使用这种方式。机制就是跟踪一个值的引用次数,当声明一个变量并将一个引用类型赋值给该变量时该值引用次数加1,当这个变量指向其他一个时该值的引用次数便减一。当该值引用次数为0时,则说明没有办法再访问这个值了,被视为准备回收的对象,每当过一段时间开始垃圾回收的时候,就把被引用数为0的变量回收。引用计数方法可能导致循环引用,类似死锁,导致内存泄露。
例如:

function problem() {
    var objA = new Object();
    var objB = new Object();
    objA.someOtherObject = objB;
    objB.anotherObject = objA;
}

objA和objB相互引用,两个对象的引用次数都是2。函数执行完成之后,objA和objB还将会继续存在,因为他们的引用次数永远不会是0。这样的相互引用如果说很大量的存在就会导致大量的内存泄露。

内存泄漏

定义:程序中己动态分配的堆内存由于某种原因程序未释放或无法释放引发的各种问题。
js中可能出现的内存泄漏原因:
(1)全局变量引起的内存泄露
(2)闭包引起的内存泄露:慎用闭包
(3)dom清空或删除时,事件未清除导致的内存泄漏
(4)循环引用带来的内存泄露

闭包

  闭包就是能够读取其他函数内部变量的函数,或者子函数在外调用,子函数所在的父函数的作用域不会被释放。基本上就是一个函数内部返回一个函数。
  我们开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部的引用,从而使函数内部的值可以得以保留。

  • 好处:可以读取函数内部的变量、将变量始终保持在内存中、可以封装对象的私有属性和私有方法
  • 坏处:比较耗费内存、使用不当会造成内存溢出的问题

== 和 ===的区别

==是非严格意义上的相等,值相等就相等,会进行数据类型转换。
===是严格意义上的相等,会比较两边的数据类型和值大小,值和引用地址都相等才相等

跨域的原理

  跨域是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对 JavaScript 实施的安全限制,那么只要协议、域名、端口有任何一个不同,都被当作是不同的域。

如何解决跨域

  1. jsonp跨域:通过动态创建 script,再请求一个带参网址实现跨域通信。
  2. document.domain + iframe 跨域:两个页面都通过 js 强制设置 document.domain 为基础主域,就实现了同域。
  3. nodejs中间件代理跨域;
  4. 后端在头部信息里面设置安全域名;

严格模式的限制

变量必须声明后再使用;
函数的参数不能有同名属性,否则报错;
不能使用 with 语句;
禁止 this 指向全局对象;

attribute 和 property 的区别

(1)attribute 是 dom 元素在文档中作为 html 标签拥有的属性;property 就是 dom 元素在 js 中作为对象拥有的属性。
(2)Property的属性值可以是任意类型,attribute的属性值类型只能是string类型
(3)Property包含attribute中HTML自带的属性,不包含自定义属性
(4)attribute的值更像是初始值,会同步到property中。Attribute的值的修改也会同步到property中,但property修改则不会映射到attribute

异步编程的实现方式

(1)回调函数
优点:简单、容易理解
缺点:不利于维护、代码耦合高
(2)事件监听
优点:容易理解,可以绑定多个事件,每个事件可以指定多个回调函数
缺点:事件驱动型,流程不够清晰
(3)发布/订阅(观察者模式)
类似于事件监听,但是可以通过‘消息中心’,了解现在有多少发布者,多少订阅者
(4)Promise 对象
优点:可以利用 then 方法,进行链式写法;可以书写错误时的回调函数
缺点:编写和理解,相对比较难
(5)Generator 函数
优点:函数体内外的数据交换、错误处理机制
缺点:流程管理不方便
(6)async 函数
优点:内置执行器、更好的语义、更广的适用性、返回的是 Promise、结构清晰
缺点:错误处理机制

项目性能优化

减少 HTTP 请求数;减少 DNS 查询;避免重定向;图片懒加载;减少 DOM 元素数量;减少 DOM 操作;
使用外部 JavaScript 和 CSS;压缩 JavaScript、CSS、字体、图片等;优化 CSS Sprite;
尽量减少 iframe 使用;避免图片 src 为空;把样式表放在 link 中;把 JavaScript 放在页面底部;

负载均衡

多台服务器共同协作,不让其中某一台或几台超额工作,发挥服务器的最大作用
(1)http 重定向负载均衡:调度者根据策略选择服务器以 302 响应请求,缺点只有第一次有效果,后续操作维持在该服务器 (2)dns 负载均衡:解析域名时,访问多个 ip 服务器中的一个
(3)反向代理负载均衡:访问统一的服务器,由服务器进行调度访问实际的某个服务器,对统一的服务器要求大,性能受到服务器群的数量

原型、原型链、继承

所有的函数都有prototype属性(原型);所有的对象都有__proto__属性
在Javascript中,每个函数都有一个原型属性prototype指向自身的原型,而由这个函数创建的对象也有一个__proto__属性指向这个原型,而函数的原型是一个对象,所以这个对象也会有一个__proto__指向自己的原型,这样逐层深入直到找到Object对象的原型,这样就形成了原型链。

HTML和HTML5区别

主要有三个区别:
1、文档声明区别
HTML:超文本标记语言,一种纯文本类型的语言。
HTML5.0:文档声明HTML5方便书写,精简,有利于程序员快速的阅读和开发。
2、结构语义区别
html:没有体现结构语义化的标签,如:


html5:添加了许多具有语义化的标签,如:

CSS选择器以及优先级的理解

常用的CSS选择器
ID选择器、类选择器、标签选择器、属性选择器、伪类选择器、后代选择器
!important > 内联样式 > ID选择器 > 类选择器 > (标签选择器、伪类选择器、属性选择器)
css 预编译器(预处理器):Less;Sass;stylus
块元素
address地址、blockquote块引用、center举中对齐块、dir目录列表、div 、dl定义列表、form交互表单、h1–h6标题、hr水平分隔线、menu菜单列表、noframesframes可选内容、noscript可选脚本内容(对于不支持script的浏览器显示此内容)、ol有序表单、p段落、pre格式化文本、table表格、ul无序列表

表单中readonly和disabled的区别

共同点:能够使用户不能改变表单中的内容
不同点:
1、readonly只对input和textarea有效,但是disabled对所有的表单元素都是有效的,包括radio、checkbox
2、readonly可以获取到焦点,只是不能修改。disabled设置的文本框无法获取焦点
3、如果表单的字段是disabled,则该字段不会发送(表单传值)和序列化

请说出至少三种减少页面加载时间的方法

尽量减少页面中重复的http请求;
css样式放置在文件头部、js脚本放置在文件末尾;
压缩合并js、css代码;
服务器开启gzip压缩;

懒加载

懒加载也叫延迟加载,指在长网页中延迟加载图像,主要目的是作为服务器前端的优化,减少请求数或延迟请求数。实现方式:(1)使用定时器(setTimeOut 或 setInterval)进行加载延迟。
(2)条件加载:符合某些条件才开始加载。(3)可视区加载,主要由滚动监听来实现。一般会在距用户看到某图片前一定距离才开始加载,这样能保证用户下拉时正好能看到图片。
实现原理:将图片 src 设为空字符串,而图片的真实路径则设置在自定义属性 data-original 中。
监听页面滚动事件,判断图片是否进入可视区,如果是,那就将图片==的 src 属性值设置为 data-original 的值。

预加载

预加载就是提前加载图片,当用户需要查看时可直接从本地缓存中渲染,可减少用户等待的时间。实现方式
(1)使用img标签

(2)通过CSS的background属性将图片预加载
background: url(http://abc/image01.png)
两者都是提高页面性能有效的办法,两者主要区别是一个是提前加载,一个是延迟加载甚至不加载。
懒加载对服务器有一定的缓解压力作用,而预加载则会增加服务器的压力。

对语义化的理解?

语义化是指根据内容的结构化,选择合适的标签。通俗来讲就是用正确的标签做正确的事情。
语义化的优点如下:(1)对机器友好,带有语义的文字表现力丰富,更适合搜索引擎的爬虫爬取有效信息,有利于SEO
(2)对开发者友好,使用语义类标签增强了可读性,结构更加清晰,开发者能清晰的看出网页的结构,便于团队的开发与维护。
常见的语义化标签:

头部 导航栏
区块主要区域
主要内容 侧边栏
底部

src和href的区别

src和href都是用来引用外部的资源,它们的区别如下:
src:表示对资源的引用,它指向的内容会嵌入到当前标签所在的位置。sc会将其指向的资源下载并应用到文档内,如请求js脚本。当浏览器解析到该元素时,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,所以一般js脚本会放在页面底部。
href:表示超文本引用,建立当前元素和引用资源之间的联系。当浏览器识别到它指向的文件时,就会并行下载资源,不会停止对当前文档的处理。常用在a、link等标签上。

实现圆形可点击区域的页面上?

答案:css3,js,map加区域
一、边界半径(css3)
对于圆形,最直接的方法想到的就是css3的圆角属性,这个属性可以将html元素的形状设置为圆形,之后,可以设置事件(当然包括点击)来设置这个圆形区域。
二、通过事件坐标实现
也就是通过js进行区域判断,进而形成可点区域

渐进增强和优雅降级之间的区别

(1)渐进增强:主要是针对低版本的浏览器进行页面重构,保证基本功能情况的下,再针对高级浏览器进行效果、交互等方面的改进,以达到更好的用户体验。
(2)优雅降级:一开始就构建完整的功能,然后再针对低版本的浏览器进行兼容。

ES6中的Map和Set以及它们与Object的区别

共同点:三者都是对象
Map 和 Objects 的区别:
(1)Object的键只能是字符串或者Symbols,Map的键可以是任何类型。
(2)Map中的键值遵循FIFO原则,即有序的。而Object添加的键则不是。
(3)Map中的键值对可以通过size来计算,Object需要我们手动计算。
(4)Object 都有自己的原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。
Map:是一组键值对的结构,具有极快的查找速度。
Set:Set 对象允许你存储任何类型的唯一值(不可重复),无论是原始值或者是对象引用。
语法:new Set([]) | new Set(string);

常用的meta标签有哪些

meta标签由name和content属性定义,用来描述网页文档的属性,比如网页的作者,网页描述,关键词等。常用的meta标签:
(1)charset,用来描述HTML文档的编码类型:
(2)keywords,页面关键词:
(3)description页面描述:<meta name="description"content=“页面描述内容”/>
(4)refresh页面重定向和刷新:<meta http-equiv="refresh"content=“0;url=”/>
(5)viewport,适配移动端,可以控制视口的大小和比例:
<meta name="viewport"content="width=device-width,initial-scale=1,maximum-scale=1”>
其中,content参数有以下几种:
width viewport:宽度,让视口的宽度与设备一致
height viewport高度
initial-.scale:初始缩放比例 maximum-scale:最大缩放比例 minimum-scale最小缩放比例
user-scalable:是否允许用户缩放
(6)搜索引擎索引方式:
<meta name="robots"content=“index,follow”/>
其中,content参数有以下几种:
a11:文件将被检索,且页面上的链接可以被查询:
none:文件将不被检索,且页面上的链接不可以被查询:
index:文件将被检索:Follow:页面上的链接可以被查询;
noindex:文件将不被检索;nofo11ow:页面上的链接不可以被查询。

一个页面上有大量的图片(大型电商网站),加载很慢,你有哪些方法优化这些图片的加载,给用户更好的体验。

图片懒加载,在页面上的未可视区域河以添加一个滚动条事件,判断图片位置与浏览器顶端的距离与页面的距离,如果前者小于后者,优先加载。
1.如果为幻灯片、相册等,可以使用图片预加载技术,将当前展示图片的前一张和后一张优先下载。
2.如果图片为css图片,可以使用CSSsprite,SVGsprite,Iconfont、Base64等技术。
3.如果图片过大,可以使用特殊编码的图片,加载时会先加载一张压缩的特别厉害的缩略图,以提高用户体验。
4.如果图片展示区域小于图片的真实大小,则根据业务需要先行进行图片压缩,图片压缩后大小与展示一致。

DOM和BOM有什么区别?

DOM:文档对象模型;DOM是用于操作API的文档,文档是其对象;
DOM与文档有关,文档指的是网页,也就是html文档。DOM与浏览器无关,他关注的是网页本身的内容。
BOM:浏览器对象模型;BOM是操作浏览器出现的API,窗口是其对象;window对象既提供API javascript访问浏览器,同时充当全局对象在ECMAScript

如何实现浏览器内多个标签页之间的通信?

WebSocket,SharedWorker;也可以调用localStorage、cookies等本地存储方式;
localStorage在另一个浏览上下文里被添加、修改或删除时,它都会触发一个事件,我们通过监听事件,控制它的值来进行页面信息通信。
注意:Safari在无痕模式下设置localStorage值时会抛出QuotaExceededError的异常:

浏览器乱码的原因是什么?如何解决?

产生乱码的原因:
(1)网页源代码是gbk 的编码,而内容中的中文字是utf-8编码的,这样浏览器打开即会出现html 乱码,反之也会出现乱码;(2)html 网页编码是 gbk,而程序从数据库中调出的内容使用的是utf-8 编码,也会造成编码乱码;
(3)浏览器不能自动检测网页编码,造成网页乱码。
解决办法:
(1)使用软件编辑HTML网页内容;
(2)如果网页设置编码是 gbk,而数据库储存数据编码格式是UTF-8,此时需要程序查询数据库数据,进行程序转码;
(3)在浏览器中找到转换编码的菜单进行转换。

img的srcset属性的作用?

响应式页面中经常根据屏幕密度设置不同的图片。这时就用到了img标签的srcset属性。srcset属性用于设置不同屏幕密
度下,img会自动加载不同的图片。用法如下:
<img src="image-128.png"srcset=“image-256.png 2x”/>
使用上面的代码,就能实现在屏幕密度为1x的情况下加载image-128.png,屏幕密度为2x时加载image-256.png。

HTML5应用程序缓存和浏览器缓存有什么区别?

  应用程序缓存是HTML5的重要特性之一,提供了离线使用功能,让应用程序可以获取本地的网站内容,例如CSS、图片以及Javascript。这个特性可以提高网站性能,它的实现借助于manifest文件,代码如下:

<html manifest="example.appcache"></html>

与传统浏览器缓存相比,它不强制缓存用户访问的网站内容。

浏览器是如何对HTML5的离线储存资源进行管理和加载?

(1)在线的情况下,浏览器发现html头部有manifest属性,它会请求manifest文件,如果是第一次访问页面,那么浏览器就会根据manifest文件的内容下载相应的资源并且进行离线存储。如果已经访问过页面并且资源已经进行离线存储了,那么浏览器就会使用离线的资源加载页面,然后浏览器会对比新的manifest文件与旧的manifest文件,如果文件没有发生改变,就不做任何操作,如果文件改变了,就会重新下载文件中的资源并进行离线存储。
(2)离线的情况下,浏览器会直接使用离线存储的资源。

三种对象 JS中,可以将对象分为“内部对象”、“宿主对象”和“自定义对象”三种。

1,内部对象
  js中的内部对象包括Array、Boolean、Date、Function、Global、Math、Number、Object、RegExp、String以及各种错误类对
象,包括Error、EvalError、RangeError、ReferenceError、SyntaxError和TypeError。其中Global和Math这两个对象又被称为“内置对象”,这两个对象在脚本程序初始化时被创建不必实例化这两个对象。
2.宿主对象
宿主对象就是执行JS脚本的环境提供的对象。对于嵌入到网页中的JS来说,其宿主对象就是浏览器提供的对象,所以又称为浏览器对象,如IE、Firefox等浏览器提供的对象。不同的浏览器提供的宿主对象可能不同。浏览器对象有很多,如Window和Documen,Element, form, image,等等。
3.自定义对象 顾名思义,就是开发人员自己定义的对象。JS允许使用自定义对象,使JS应用及功能得到扩充

一个iframe,内嵌了一个A页面,iframe的宽高不停变化,如何让A页面的宽高自适应这个iframe的宽高大小实时。

css的方案;Onresize;监听鼠标动作,鼠标释放后重新定宽;

说一下 http 和 https

(1)http 和 https 的基本概念
http: 超文本传输协议,是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP)。
https: 是由 http 和 ssl 协议构建的可进行加密传输和身份认证的网络协议,比 http 协议的安全性更高。https 的 SSL 加密是在传输层实现的。 https 协议的主要作用是:建立一个信息安全通道,来确保数据的传输,确保网站的真实性。
(2)http 和 https 的区别?
http 传输的数据都是未加密的,也就是明文的。https 则是具有安全性的 ssl 加密传输协议。使用不同的链接方式,端口也不同,http 协议的端口为 80,https 的端口为443。
(3)https 协议的工作原理
客户端在使用 HTTPS 方式与 Web 服务器通信时有以下几个步骤。
客户使用 https url 访问服务器,则要求 web 服务器建立 ssl 链接。
web 服务器接收到客户端的请求之后,会将网站的证书(证书中包含了公钥),返回或者说传输给客户端。
客户端和 web 服务器端开始协商 SSL 链接的安全等级,也就是加密等级。
客户端浏览器通过双方协商一致的安全等级,建立会话密钥,然后通过网站的公钥来加密会话密钥,并传送给网站。
web 服务器通过自己的私钥解密出会话密钥,通过会话密钥加密与客户端之间的通信。
(4)https 协议的优点
使用 HTTPS 协议可认证用户和服务器,确保数据发送到正确的客户机和服务器;
可防止数据在传输过程中不被窃取、改变,确保数据的完整性。 HTTPS 是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本。
(5)https 协议的缺点
https 握手阶段比较费时,会使页面加载时间延长 50%,增加 10%~20%的耗电。
https 缓存不如 http 高效,会增加数据开销。
SSL 证书也需要钱,功能越强大的证书费用越高。
SSL 证书需要绑定 IP,不能再同一个 ip 上绑定多个域名,ipv4 资源支持不了这种消耗。

说一下 http2.0

(1)提升访问速度(可以对于,请求资源所需时间更少,访问速度更快,相比 http1.0)。
(2)允许多路复用:多路复用允许同时通过单一的 HTTP/2 连接发送多重请求-响应信息。改善了:在 http1.1 中,浏览器客户端在同一时间,针对同一域名下的请求有一定数量限制(连接数量),超过限制会被阻塞。
(3)二进制分帧:HTTP2.0 会将所有的传输信息分割为更小的信息或者帧,并对他们进行二进制编码
(4)首部压缩
(5)服务器端推送

TCP 和 UDP 的区别

(1)TCP 是面向连接的,udp 是无连接的即发送数据前不需要先建立链接。
(2)TCP 提供可靠的服务。也就是说,通过 TCP 连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP 尽最大努力交付,即不保证可靠交付。所以 tcp 适合大数据量的交换。
(3)TCP 是面向字节流,UDP 面向报文,并且网络出现拥塞不会使得发送速率降低(因此会出现丢包,对实时的应用比如 IP 电话和视频会议等)。
(4)TCP 只能是 1 对 1 的,UDP 支持 1 对 1,1 对多。
(5)TCP 的首部较大为 20 字节,而 UDP 只有 8 字节。
(6)TCP 是面向连接的可靠性传输,而 UDP 是不可靠的。

WebSocket 的实现和应用

WebSocket的作用如下。它是web应用程序的传输协议,提供了双向的、按序到达的数据流。它是HTML5新增的协议,WebSocket的连接是持久的,它在客户端和服务器之间保持双工连接,服务器的更新可以及时推送到客户端,而不需要客户端以一定的时间间隔去查询。
(2)WebSocket 是什么样的协议,具体有什么优点?
HTTP 的生命周期通过 Request 来界定,也就是 Request 一个 Response,那么在 Http1.0 协议中,这次 Http 请求就结束了。在 Http1.1 中进行了改进,是指有一个 connection: Keep-alive,也就是说,在一个 Http 连接中,可以发送多个 Request,接收多个 Response。 但是必须记住,在 Http 中一个 Request 只能对应有一个 Response,而且这个 Response 是被动的,不能主动发起。
WebSocket 是基于 Http 协议的,或者说借用了 Http 协议来完成一部分握手,在握手阶段 与 Http 是相同的。我们来看一个 websocket 握手协议的实现,基本是 2 个属性,upgrade,connection。
基本请求如下:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
多了 2 个属性: Upgrade:webSocket Connection:Upgrade
告诉服务器发送的是 websocket
1.Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
2.Sec-WebSocket-Protocol: chat, superchat
3.Sec-WebSocket-Version: 13

几个很实用的 BOM 属性对象方法?

(1)location对象:包含当前url的信息
location.href-- 返回或设置当前文档的 URL
location.search – 返回 URL 中的查询字符串部分。
例如 http://www.dreamdu.com/dreamdu.php?id=5&name=dreamdu 返回包括(?)后面的内容
?id=5&name=dreamdu
location.hash – 返回 URL#后面的内容,如果没有#,返回空
location.host – 返回 URL 中的域名部分,例如 www.dreamdu.com
location.hostname – 返回 URL 中的主域名部分,例如 dreamdu.com
location.pathname – 返回 URL 的域名后的部分。例如 http://www.dreamdu.com/xhtml/ 返回/xhtml/
location.port – 返回 URL 中的端口部分。例如 http://www.dreamdu.com:8080/xhtml/ 返回8080
location.protocol – 返回 URL 中的协议部分。例如 http://www.dreamdu.com:8080/xhtml/ 返回(//)前面的内容 http:
location.assign – 设置当前文档的 URL
location.replace() – 设置当前文档的 URL,并且在 history 对象的地址列表中移除这个URL location.replace(url); location.reload() – 重载当前页面
(2)history 对象:包含用户访问过的url
history.go() – 前进或后退指定的页面数 history.go(num);
history.back() – 后退一页
history.forward() – 前进一页
(3)Navigator 对象:包含有关浏览器的信息
navigator.userAgent – 返回用户代理头的字符串表示(就是包括浏览器版本信息等的字符串)
navigator.cookieEnabled – 返回浏览器是否支持(启用)cookie

说一下 HTML5 drag api

dragstart:事件主体是被拖放元素,在开始拖放被拖放元素时触发,。
darg:事件主体是被拖放元素,在正在拖放被拖放元素时触发。
dragenter:事件主体是目标元素,在被拖放元素进入某元素时触发。
dragover:事件主体是目标元素,在被拖放在某元素内移动时触发。
dragleave:事件主体是目标元素,在被拖放元素移出目标元素时触发。
drop:事件主体是目标元素,在目标元素完全接受被拖放元素时触发。
dragend:事件主体是被拖放元素,在整个拖放操作结束时触发

补充 400 和 401、403 状态码

(1)400 状态码:请求无效
产生原因: 前端提交数据的字段名称和字段类型与后台的实体没有保持一致;
前端提交到后台的数据应该是 json 字符串类型,但是前端没有将对象 JSON.stringify 转化成字符串。
解决方法:对照字段的名称,保持一致性;将 obj 对象通过 JSON.stringify 实现序列化
(2)401 状态码:当前请求需要用户验证
(3)403 状态码:服务器已经得到请求,但是拒绝执行

fetch 发送 2 次请求的原因

fetch 发送 post 请求的时候,总是发送 2 次,第一次状态码是 204,第二次才成功?
原因很简单,因为用 fetch 的 post 请求的时候,导致 fetch 第一次发送了一个 Options 请求,询问服务器是否支持修改的请求头,如果服务器支持,则在第二次中发送真正的请求。

web worker

在 HTML 页面中,如果在执行脚本时,页面的状态是不可响应的,直到脚本执行完成后,页面才变成可响应。web worker 是运行在后台的js,独立于其他脚本,不会影响页面的性能。并且通过 postMessage 将结果回传到主线程。这样在进行复杂操作的时候,就不会阻塞主线程了。
如何创建webworker:检测浏览器对于webworker的支持性;创建webworker文件(js,回传函数等);创建webworker对象
Cookie 如何防范 XSS 攻击
XSS(跨站脚本攻击)是指攻击者在返回的 HTML 中嵌入 javascript 脚本,为了减轻这些攻击,需要在 HTTP 头部配上,set-cookie: httponly-这个属性可以防止 XSS,它会禁止 javascript 脚本来访问 cookie。
secure - 这个属性告诉浏览器仅在请求为 https 的时候发送 cookie。
结果应该是这样的:Set-Cookie=…

介绍知道的 http 返回的状态码

100 Continue 继续。客户端应继续其请求
101 Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到 HTTP 的新版本协议
200 OK 请求成功。一般用于 GET 与 POST 请求
201 Created 已创建。成功请求并创建了新的资源
202 Accepted 已接受。已经接受请求,但未处理完成
203 Non-Authoritative Information 非授权信息。请求成功。但返回的 meta 信息不在原始的服务器,而是一个副本
204 No Content 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
205 Reset Content 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
206 Partial Content 部分内容。服务器成功处理了部分 GET 请求
300 Multiple Choices 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301 Moved Permanently 永久移动。请求的资源已被永久的移动到新 URI,返回信息会包括新的 URI,浏览器会自动定向到新 URI。今后任何新的请求都应使用新的 URI 代替
302 Found 临时移动。与 301 类似。但资源只是临时被移动。客户端应继续使用原有 URI
303 See Other 查看其它地址。与 301 类似。使用 GET 和 POST 请求查看
304 Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305 Use Proxy 使用代理。所请求的资源必须通过代理访问
306 Unused 已经被废弃的 HTTP 状态码
307 Temporary Redirect 临时重定向。与 302 类似。使用 GET 请求重定向
400 Bad Request 客户端请求的语法错误,服务器无法理解
401 Unauthorized 请求要求用户的身份认证
402 Payment Required 保留,将来使用
403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求
404 Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
405 Method Not Allowed 客户端请求中的方法被禁止
406 Not Acceptable 服务器无法根据客户端请求的内容特性完成请求
407 Proxy Authentication Required 请求要求代理的身份认证,与 401 类似,但请求者应当使用代理进行授权
408 Request Time-out 服务器等待客户端发送的请求时间过长,超时
409 Conflict 服务器完成客户端的 PUT 请求是可能返回此代码,服务器处理请求时发生了冲突
410 Gone 客户端请求的资源已经不存在。410 不同于 404,如果资源以前有现在被永久删除了可使用 410 代码,网站设计人员可通过 301 代码指定资源的新位置
411 Length Required 服务器无法处理客户端发送的不带 Content-Length 的请求信息
412 Precondition Failed 客户端请求信息的先决条件错误
413 Request Entity Too Large 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个 Retry-After 的响应信息
414 Request-URI Too Large 请求的 URI 过长(URI 通常为网址),服务器无法处理
415 Unsupported Media Type 服务器无法处理请求附带的媒体格式
416 Requested range not satisfiable 客户端请求的范围无效
417 Expectation Failed 服务器无法满足 Expect 的请求头信息
500 Internal Server Error 服务器内部错误,无法完成请求
501 Not Implemented 服务器不支持请求的功能,无法完成请求
502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
503 Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的 Retry-After 头信息中
504 Gateway Time-out 充当网关或代理的服务器,未及时从远端服务器获取请求
505 HTTP Version not supported 服务器不支持请求的 HTTP 协议的版本,无法完成处理

讲讲 304

304:如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自 上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个 304 状态码。

强缓存、协商缓存什么时候用哪个

因为服务器上的资源不是一直固定不变的,大多数情况下它会更新,这个时候如果我们 还访问本地缓存,那么对用户来说,那就相当于资源没有更新,用户看到的还是旧的资源;所以我们希望服务器上的资源更新了浏览器就请求新的资源,没有更新就使用本地的缓存,以最大程度的减少因网络请求而产生的资源浪费。

GET 和 POST 的区别

(1)get 参数通过 url 传递,post 放在 request body 中。
(2)get 请求在 url 中传递的参数是有长度限制的,而 post 没有。
(3)get 比 post 更不安全,因为参数直接暴露在 url 中,所以不能用来传递敏感信息。
(4)get 请求只能进行 url 编码,而 post 支持多种编码方式
(5)get 请求参数会被完整保留在浏览历史记录里,而 post 中的参数不会被保留。
(6)GET 产生一个 TCP 数据包;POST 产生两个 TCP 数据包。
(7)GET 和 POST 本质上就是 TCP 链接。由于 HTTP 的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。
(8)GET - 从指定的资源请求数据。 POST - 向指定的资源提交要被处理的数据。
(9)对于 GET 方式的请求,浏览器会把 http header 和 data 一并发送出去,服务器响应 200 ;
而对于 POST,浏览器先发送 header,服务器响应 100 continue,浏览器再发送 data,服务器响应 200 ok。
(10)get 请求类似于查找的过程,用户获取数据,可以不用每次都与数据库连接,所以可以使用缓存。
post 不同,post 做的一般是修改和删除的工作,所以必须与数据库交互,所以不能使用缓存。因此 get 请求适合于请求缓存。

get 请求传参长度的误区

误区:我们经常说 get 请求参数的大小存在限制,而 post 请求的参数大小是无限制的。 实际上 HTTP 协议从未规定 GET/POST 的请求长度限制是多少。对 get 请求参数的限制是来源与浏览器或 web 服务器,浏览器或 web 服务器限制了 url 的长度。为了明确这个概念,我们必须再次强调下面几点:
HTTP 协议未规定 GET 和 POST 的长度限制,GET 的最大长度显示是因为浏览器和 web服务器限制了 URI 的长度。不同的浏览器和 WEB 服务器,限制的最大长度不一样

状态码 304 和 200

状态码 200:请求已成功,请求所希望的响应头或数据体将随此响应返回。即返回的数 据为全量的数据,如果文件不通过 GZIP 压缩的话,文件是多大,则要有多大传输量。状态码 304:如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码。即客户端和服务器端只需要传输很少的数据量来做文件的校验,如果文件没有修改过,则不需要返回全量的数据。

在地址栏里输入一个 URL,到这个页面呈现出来,中间会发生什么?

输入 url 后,首先需要找到这个 url 域名的服务器 ip,为了寻找这个 ip,浏览器首先会寻找缓存,查看缓存中是否有记录,缓存的查找记录为:浏览器缓存-》系统缓存-》路由器缓存。缓存中没有则查找系统的 hosts 文件中是否有记录,如果没有则查询 DNS 服务器,得到服务器的 ip 地址后,浏览器根据这个 ip 以及相应的端口号,构造一个 http 请求,这个请求报文会包括这次请求的信息,主要是请求方法,请求说明和请求附带的数据,并将这个 http 请求封装在一个 tcp 包中。这个 tcp 包会依次经过传输层,网络层,数据链路层,物理层到达服务器。服务器解析这个请求来作出响应,返回相应的 html给浏览器。
因为 html 是一个树形结构,浏览器根据这个 html 来构建 DOM 树,在 dom 树的构建过程中如果遇到 JS 脚本和外部 JS 连接,则会停止构建 DOM 树来执行和下载相应的代码,这会造成阻塞,这就是为什么推荐 JS 代码应该放在 html 代码的后面,之后根据外部样式,内部样式,内联样式构建一个 CSS 对象模型树,构建完成后和 DOM 树合并为渲染树。这里主要做的是排除非视觉节点,比如 script,meta 标签和排除 display 为 none 的节点,之后进行布局,布局主要是确定各个元素的位置和尺寸,之后是渲染页面,因为 html 文件中会含有图片,视频,音频等资源,在解析 DOM 的过程中,遇到这些都会进行并行下载,浏览器对每个域的并行下载数量有一定的限制,一般是 4-6 个,当然在这些所有的请求中我们还需要关注的就是缓存,缓存一般通过Cache-Control、Last-Modify、Expires 等首部字段控制。

Cache-Control 和 Expires 的区别:

expires存的是个服务端绝对时间,修改客户端系统时间会有影响。
cache-control是相对时间,即使客户端时间发生改变,相对时间也不会随之改变。例如设置max-age=10s,那么在10s以内,使用浏览器缓存的资源。cache-control的优先级高于expires
因为存在时差问题,一般采用 Cache-Control,在请求这些有设置了缓存的数据时,会先查看是否过期,如果没有过期则直接使用本地缓存,过期则请求并在服务器校验文件是否修改。如果上一次响应设置了 ETag 值会在这次请求的时候作为 If-None-Match 的值交给服务器校验,如果一致,继续校验 Last-Modified,没有设置 ETag 则直接验证 Last-Modified,再决定是否返回 304。

cache-control 的值有哪些

cache-control 是一个通用消息头字段被用于 HTTP 请求和响应中,通过指定指令来实现缓存机制,这个缓存指令是单向的,常见的取值有 private、no-cache、max-age、must-revalidate 等,默认为 private。

为什么利用多个域名来存储网站资源会更有效?

CDN缓存更方便;突破浏览器并发限制;节约cookie带宽;节约主域名的连接数,优化页面响应速度;防止不必要的安全问题;

常见的 HTTP 的头部

可以将 http 首部分为通用首部,请求首部,响应首部,实体首部
通用首部表示一些通用信息,比如 date 表示报文创建时间,
请求首部就是请求报文中独有的,如 cookie,和缓存相关的如 if-Modified-Since
响应首部就是响应报文中独有的,如 set-cookie,和重定向相关的 location,
实体首部用来描述实体部分,如 allow 用来描述可执行的请求方法,content-type 描述主题类型,content-Encoding 描述主体的编码方式。
 csrf 和 xss 的网络攻击及防范
CSRF:跨站请求伪造,可以理解为攻击者盗用了用户的身份,以用户的名义发送了恶意请求,比如用户登录了一个网站后,立刻在另一个tab页面访问量攻击者用来制造攻击的网站,这个网站要求访问刚刚登陆的网站,并发送了一个恶意请求,这时候 CSRF就产生了,比如这个制造攻击的网站使用一张图片,但是这种图片的链接却是可以修改数据库的,这时候攻击者就可以以用户的名义操作这个数据库,防御方式的话:使用验证码,检查 https 头部的 refer,使用 token
XSS:跨站脚本攻击,是说攻击者通过注入恶意的脚本,在用户浏览网页的时候进行攻击,比如获取 cookie,或者其他用户身份信息,可以分为存储型和反射型,存储型是攻击者输入一些数据并且存储到了数据库中,其他浏览者看到的时候进行攻击,反射型的话不存储在数据库中,往往表现为将攻击代码放在 url 地址的请求参数中,防御的话为cookie 设置 httpOnly 属性,对用户的输入进行检查,进行特殊字符过滤。

描述一下 XSS 和 CRSF 攻击?防御方法?

XSS 防御的总体思路是:对输入(和 URL 参数)进行过滤,对输出进行编码。也就是对提交的所有内容进行过滤,对 url 中的参数进行过滤,过滤掉会导致脚本执行的相关内容;然后对动态输出到页面的内容进行 html 编码,使脚本无法在浏览器中执行。虽然对输入过滤可以被绕过,但是也还是会拦截很大一部分的 XSS 攻击。
防御 CSRF 攻击主要有三种策略:验证 HTTP Referer 字段;在请求地址中添加 token 并验证;在 HTTP 头中自定义属性并验证。

cookie 有哪些字段可以设置

name 字段为一个 cookie 的名称。
value 字段为一个 cookie 的值。
domain 字段为可以访问此 cookie 的域名。
path 字段为可以访问此 cookie 的页面路径。 比如 domain 是 abc.com,path 是/test,那么只有/test 路径下的页面可以读取此 cookie。
expires/Max-Age 字段为此 cookie 超时时间。若设置其值为一个时间,那么当到达此时间后,此 cookie 失效。不设置的话默认值是 Session,意思是 cookie 会和 session 一起失效。 当浏览器关闭(不是浏览器标签页,而是整个浏览器) 后,此 cookie 失效。
Size 字段为此 cookie 大小。
http字段:cookie的httponly属性。若此属性为true,则只有在http请求头中会带有此cookie的信息,而不能通过 document.cookie 来访问此 cookie。
secure 字段:设置是否只能通过 https 来传递此条 cookie

HTML5 和 CSS3 用的多吗?你了解它们的新属性吗?有在项目中用过吗?

html5:
1)标签增删
8 个语义元素 header section footer aside nav main article figure
内容元素 mark 高亮 progress 进度
新的表单控件 calander date time email url search
新的 input 类型 color date datetime datetime-local email
移除过时标签 big font frame frameset
2)canvas 绘图,支持内联 SVG。支持 MathML
3)多媒体 audio video source embed track
4)本地离线存储,把需要离线存储在本地的文件列在一个 manifest 配置文件
5)web 存储。localStorage、SessionStorage
css3:
CSS3边框如border-radius,box-shadow等;
CSS3背景如background-size,background-origin 等;CSS3 2D,3D 转换如 transform 等;CSS3 动画如 animation 等。

画一条 0.5px 的线

(1)meta viewport

1px的线通过 meta viewport中scale的设置,可以缩放变成0.5倍,则得到0.5px的线。但是viewport仅限于移动端。
(2)transform:scale()该方法用来定义元素的2D 缩放转换
#line{
border-bottom:1px solid black;
transform:scale(0.5,0.5);
transform-origin: 50% 100%; /为了防止线模糊/
}
(3)通过box-shadow

box-shadow: 0 0.5px 0 #000

(4)svg、canvas画图
(5)创建伪元素去实现。用transform去实现的话会发现,伪元素的实际尺寸是没有发生变化的,但是效果是会出现的,因为transform的属性值(translate移动; scale缩放; rotate旋转;skew倾斜)是不会占用页面的实际尺寸值的,所有用检查器去检查也会发现它的实际尺寸还是1px。
div::before{
/margin-bottom:50px;/
content:“”;
display:block;
height:1px;
background-color:red;
transform:scale(0.5);
position:absolute;
left:-50%;
width:200%;
}

解决css污染

第一个:scoped 属性
第二个:css in js
第三个:CSS Modules
transition 和 animation 的区别
Animation 和 transition 大部分属性是相同的,他们都是随时间改变元素的属性值,他们的主要区别是 transition 需要触发一个事件才能改变属性,而 animation 不需要触发任何事件的情况下才会随时间改变属性值,并且 transition 为 2 帧,从 from … to,而 animation 可以一帧一帧的。
div+css的布局较table布局有什么优点?
1.改版的时候更方便只要改css文件。2.页面加载速度更快、结构化清晰、页面显示简洁。
3.表现与结构相分离。4.易于优化(seo)搜索引擎更友好,排名更容易靠前
双边距重叠问题(外边距折叠)
多个相邻(兄弟或者父子关系)普通流的块元素垂直方向 marigin 会重叠
折叠的结果为:
两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。
两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。
两个外边距一正一负时,折叠结果是两者的相加的和。

CSS 选择器有哪些,优先级呢

id 选择器,class 选择器,标签选择器,伪元素选择器,伪类选择器等
同一元素引用了多个样式时,排在后面的样式属性的优先级高;
样式选择器的类型不同时,优先级顺序为:id 选择器 > class 选择器 > 标签选择器;
标签之间存在层级包含关系时,后代元素会继承祖先元素的样式。如果后代元素定义了与祖先元素相同的样式,则祖先元素的相同的样式属性会被覆盖。继承的样式的优先级比较低,至少比标签选择器的优先级低;带有!important 标记的样式属性的优先级最高;
样式表的来源不同时,优先级顺序为:内联样式> 内部样式 > 外部样式 > 浏览器用户
自定义样式 > 浏览器默认样式

css 动画如何实现

  创建动画序列,需要使用 animation 属性或其子属性,该属性允许配置动画时间、时长以及其他动画细节,但该属性不能配置动画的实际表现,动画的实际表现是由 @keyframes 规则实现,具体情况参见使用 keyframes 定义动画序列小节部分。
transition 也可实现动画。transition 强调过渡,是元素的一个或多个属性发生变化时产生的过渡效果,同一个元素通过两个不同的途径获取样式,而第二个途径当某种改变发生 (例如 hover)时才能获取样式,这样就会产生过渡动画。
三栏布局的实现方式,尽可能多写,浮动布局时,三个 div 的生成顺序有没有影响
三列布局又分为两种,两列定宽一列自适应,以及两侧定宽中间自适应
两列定宽一列自适应:
1、使用 float+margin: 给 div 设置 float:left,left 的 div 添加属性 margin-right:left 和 center 的间隔 px,right 的div 添加属性 margin-left:left 和 center 的宽度之和加上间隔
2、使用 float+overflow:给 div 设置 float:left,再给 right 的 div 设置 overflow:hidden。这样子两个盒子浮动,另 一个盒子触发 bfc 达到自适应
3、使用 position: 父级 div 设置 position:relative,三个子级 div 设置 position:absolute,这个要计算好盒子的宽度和间隔去设置位置,兼容性比较好,
4、使用 table 实现:父级 div 设置 display:table,设置 border-spacing:10px//设置间距,取值随意,子级 div设置 display:table-cell,这种方法兼容性好,适用于高度宽度未知的情况,但是 margin
失效,设计间隔比较麻烦,
5、flex 实现: parent 的 div 设置 display:flex;left 和 center 的 div 设置 margin-right;然后 right 的 div设置 flex:1;这样子 right 自适应,但是 flex 的兼容性不好
6、grid 实现: parent 的 div 设置 display:grid,设置 grid-template-columns 属性,固定第一列第二列宽度,第三列 auto,
对于两侧定宽中间自适应的布局,对于这种布局需要把 center 放在前面,可以采用双飞翼布局:圣杯布局,来实现,也可以使用上述方法中的 grid,table,flex,position 实现
calc 属性
Calc 用户动态计算长度值,任何长度值都可以使用 calc()函数计算,需要注意的是,运算符前后都需要保留一个空格,例如:width: calc(100% - 10px);
display:table 和本身的 table 有什么区别
Display:table 和本身 table 是相对应的,区别在于,display:table 的 css 声明能够让一个 html 元素和它的子节点像 table 元素一样,使用基于表格的 css 布局,是我们能够轻松定义一个单元格的边界,背景等样式,而不会产生因为使用了 table 那样的制表标签导致的语义化问题。
之所以现在逐渐淘汰了 table 系表格元素,是因为用 div+css 编写出来的文件比用 table 边写出来的文件小,而且 table 必须在页面完全加载后才显示,div 则是逐行显示,table 的嵌套性太多,没有 div 简洁
 z-index 的定位方法
z-index 属性设置元素的堆叠顺序,拥有更好堆叠顺序的元素会处于较低顺序元素之前, z-index 可以为负,且 z-index 只能在定位元素上奏效,该属性设置一个定位元素沿 z 轴的位置,如果为正数,离用户越近,为负数,离用户越远,它的属性值有 auto,默认, 堆叠顺序与父元素相等,number,inherit,从父元素继承 z-index 属性的值
 如果想要改变一个 DOM 元素的字体颜色,不在它本身上进行操作? 可以更改父元素的 color
 设置一个元素的背景颜色,背景颜色会填充哪些区域?
background-color 设置的背景颜色会填充元素的 content、padding、border 区域。
 属性选择器和伪类选择器的优先级:属性选择器和伪类选择器优先级相同
 两个嵌套的 div,position 都是 absolute,子 div 设置 top 属性,那么这个 top 是相对于父元素的哪个位置定位的。 margin 的外边缘

css 布局

六种布局方式总结:圣杯布局、双飞翼布局、Flex 布局、绝对定位布局、表格布局、网格布局。
圣杯布局是指布局从上到下分为 header、container、footer,然后 container 部分定为三栏布局。这种布局方式同样分为 header、container、footer。圣杯布局的缺陷在于 center 是在 container 的 padding 中的,因此宽度小的时候会出现混乱。
双飞翼布局给 center 部分包裹了一个 main 通过设置 margin 主动地把页面撑开。
Flex 布局是由 CSS3 提供的一种方便的布局方式。
绝对定位布局是给 container 设置 position: relative 和 overflow: hidden,因为绝对定位的元 素的参照物为第一个 postion 不为 static 的祖先元素。 left 向左浮动,right 向右浮动。 center 使用绝对定位,通过设置 left 和 right 并把两边撑开。 center 设置 top: 0 和 bottom: 0 使其高度撑开。
表格布局的好处是能使三栏的高度统一。
网格布局可能是最强大的布局方式了,使用起来极其方便,但目前而言,兼容性并不好。 网格布局,可以将页面分割成多个区域,或者用来定义内部元素的大小,位置,图层关系。

如何解决异步回调地狱

promise、generator、async/await

mouseover 和 mouseenter 的区别

mouseover:当鼠标移入元素或其子元素都会触发事件,所以有一个重复触发,冒泡的过程。对应的移除事件是 mouseout
mouseenter:当鼠标移除元素本身(不包含元素的子元素)会触发事件,也就是不会冒泡,对应的移除事件是 mouseleave
JS 的 new 操作符做了哪些事情
new 操作符新建了一个空对象,这个对象原型指向构造函数的 prototype,执行构造函数后返回这个对象。

JS的各种位置?

clientHeight:表示的是可视区域的高度,不包含 border 和滚动条
offsetHeight:表示可视区域的高度,包含了 border 和滚动条
scrollHeight:表示了所有区域的高度,包含了因为滚动被隐藏的部分。
clientTop:表示边框 border 的厚度,在未指定的情况下一般为 0
scrollTop:滚动后被隐藏的高度,获取对象相对于由 offsetParent 属性指定的父坐标(css定位的元素或 body 元素)距离顶端的高度。
JS 拖拽功能的实现
首先是三个事件,分别是 mousedown,mousemove,mouseup
当鼠标点击按下的时候,需要一个 tag 标识此时已经按下,可以执行 mousemove 里面的具体方法。
clientX,clientY 标识的是鼠标的坐标,分别标识横坐标和纵坐标,并且我们用 offsetX和 offsetY 来表示元素的元素的初始坐标,移动的举例应该是:
鼠标移动时候的坐标-鼠标按下去时候的坐标。
也就是说定位信息为: 鼠标移动时候的坐标-鼠标按下去时候的坐标+元素初始情况下的 offetLeft.
还有一点也是原理性的东西,也就是拖拽的同时是绝对定位,我们改变的是绝对定位条件下的 left以及 top 等等值。 补充:也可以通过 html5 的拖放(Drag 和 drop)来实现
 异步加载 JS 的方法
defer:只支持 IE 如果您的脚本不会改变文档的内容,可将 defer 属性加入到

eval 是做什么的

它的功能是将对应的字符串解析成 JS 并执行,应该避免使用,因为非常消耗性能(2 次,一次解析成 JS,一次执行)

如何理解前端模块化

前端模块化就是复杂的文件编程一个一个独立的模块,比如 JS 文件等等,分成独立的模块有利于重用(复用性)和维护(版本迭代),这样会引来模块之间相互依赖的问题,所以有了 commonJS 规范,AMD,CMD 规范等等,以及用于 JS 打包(编译等处理)的工具 webpack

Object.is 的区别

(1) ==
主要存在:强制转换成 number,nullundefined
" "0 //true
“0"0 //true
" " !=“0” //true
123
"123” //true
null
undefined //true
(2)Object.js
主要的区别就是+0!=-0 而 NaN
NaN

setTimeout、setInterval 和 requestAnimationFrame 之间的区别

http://www.cnblogs.com/xiaohuochai/p/5777186.html
与 setTimeout 和 setInterval 不同,requestAnimationFrame 不需要设置时间间隔, 大多数电脑显示器的刷新频率是 60Hz,大概相当于每秒钟重绘 60 次。大多数浏览器都会对重绘操作加以限制,不超过显示器的重绘频率,因为即使超过那个频率用户体验也不会有提升。因此,最平滑动画的最佳循环间隔是 1000ms/60,约等于 16.6ms。RAF 采用的是系统时间间隔,不会因为前面的任务,不会影响 RAF,但是如果前面的任务多的话,会响应 setTimeout 和 setInterval 真正运行时的时间间隔。
实现一个两列等高布局,讲讲思路
为了实现两列等高,可以给每列加上 padding-bottom:9999px;
margin-bottom:-9999px;同时父元素设置 overflow:hidden;

数组去重

法一:indexOf 循环去重
法二:ES6 Set 去重;Array.from(new Set(array))
法三:Object 键值对去重;把数组的值存成 Object 的 key 值,比如 Object[value1] = true,
在判断另一个值的时候,如果 Object[value2]存在的话,就说明该值是重复的。

excel导出功能的实现流程说一下?

导出的话,我们因为到处的数据量不大,所以直接采取的时候前端主导的方案,参考的现成方案实现大概的流程就是
1.调用后端接口得到要导出的数据
2.把数据简单处理一下转化成导出插件
3.把数据配置到对应的位置就行,插件会自动帮助我们生成excel文件并且自动下载到本地
追问:那如果要导出的数据量比较大怎么解决?
那可能一开始就要采用后端主导的方案了,我们可以把这个excel文件生成的过程放到服务器去做,用一个下载接口,把后端准备好的excel文件下载到我们本地就行。

封装:实现类和继承等。
去除字符串首尾空格
使用正则(^\s*)|(\s* ) 即可性能优化减少 H T T P 请求;使用内容发布网络( C D N );添加本地缓存;压缩资源文件;将 C S S 样式表放在顶部,把 j a v a s c r i p t 放在底部(浏览器的运行机制决定)避免使用 C S S 表达式;减少 D N S 查询;使用外部 j a v a s c r i p t 和 C S S ;避免重定向;图片 l a z y L o a d 能来讲讲 J S 的语言特性吗运行在客户端浏览器上;不用预编译,直接解析执行代码;是弱类型语言,较为灵活;与操作系统无关,跨平台的语言;脚本语言、解释性语言 t h i s 的指向哪几种默认绑定:全局环境中, t h i s 默认绑定到 w i n d o w 。隐式绑定:一般地,被直接对象所包含的函数调用时,也称为方法调用, t h i s 隐式绑定到该直接对象。隐式丢失:隐式丢失是指被隐式绑定的函数丢失绑定对象,从而默认绑定到 w i n d o w 。显式绑定:通过 c a l l ( ) 、 a p p l y ( ) 、 b i n d ( ) 方法把对象绑定到 t h i s 上,叫做显式绑定。 n e w 绑定:如果函数或者方法调用之前带有关键字 n e w ,它就构成构造函数调用。对于 t h i s 绑定来说,称为 n e w 绑定。【 1 】构造函数通常不使用 r e t u r n 关键字,它们通常初始化新对象,当构造函数的函数体执行完毕时,它会显式返回。在这种情况下,构造函数调用表达式的计算结果就是这个新对象的值。【 2 】如果构造函数使用 r e t u r n 语句但没有指定返回值,或者返回一个原始值,那么这时将忽略返回值,同时使用这个新对象作为调用结果。【 3 】如果构造函数显式地使用 r e t u r n 语句返回一个对象,那么调用表达式的值就是这个对象。 A n g u l a r J S 双向绑定原理 A n g u l a r 将双向绑定转换为一堆 w a t c h 表达式,然后递归这些表达式检查是否发生过变化,如果变了则执行相应的 w a t c h e r 函数(指 v i e w 上的指令,如 n g − b i n d , n g − s h o w 等或是 )。等到 m o d e l 中的值不再发生变化,也就不会再有 w a t c h e r 被触发,一个完整的 d i g e s t 循环就完成了。 A n g u l a r 中在 v i e w 上声明的事件指令,如: n g − c l i c k 、 n g − c h a n g e 等,会将浏览器的事件转发给 )即可 性能优化 减少 HTTP 请求;使用内容发布网络(CDN);添加本地缓存;压缩资源文件; 将 CSS 样式表放在顶部,把 javascript 放在底部(浏览器的运行机制决定) 避免使用 CSS 表达式;减少 DNS 查询;使用外部 javascript 和 CSS ; 避免重定向;图片 lazyLoad 能来讲讲 JS 的语言特性吗 运行在客户端浏览器上;不用预编译,直接解析执行代码; 是弱类型语言,较为灵活;与操作系统无关,跨平台的语言;脚本语言、解释性语言 this 的指向哪几种 默认绑定:全局环境中,this 默认绑定到 window。 隐式绑定:一般地,被直接对象所包含的函数调用时,也称为方法调用,this 隐式绑定到该直接对象。 隐式丢失:隐式丢失是指被隐式绑定的函数丢失绑定对象,从而默认绑定到 window。 显式绑定:通过 call()、apply()、bind()方法把对象绑定到 this 上,叫做显式绑定。 new 绑定:如果函数或者方法调用之前带有关键字 new,它就构成构造函数调用。对于this 绑定来说,称为 new 绑定。 【1】构造函数通常不使用 return 关键字,它们通常初始化新对象,当构造函数的函数体执行完毕时,它会显式返回。在这种情况下,构造函数调用表达式的计算结果就是这个新对象的值。 【2】如果构造函数使用 return 语句但没有指定返回值,或者返回一个原始值,那么这时将忽略返回值,同时使用这个新对象作为调用结果。 【3】如果构造函数显式地使用 return 语句返回一个对象,那么调用表达式的值就是这个对象。 AngularJS 双向绑定原理 Angular 将双向绑定转换为一堆 watch 表达式,然后递归这些表达式检查是否发生过变化,如果变了则执行相应的 watcher 函数(指 view 上的指令,如 ng-bind,ng-show 等或是{{}})。 等到 model 中的值不再发生变化,也就不会再有 watcher 被触发,一个完整的 digest 循环就完成了。 Angular 中在 view 上声明的事件指令,如:ng-click、ng-change 等,会将浏览器的事件转发给 )即可性能优化减少HTTP请求;使用内容发布网络(CDN);添加本地缓存;压缩资源文件;将CSS样式表放在顶部,把javascript放在底部(浏览器的运行机制决定)避免使用CSS表达式;减少DNS查询;使用外部javascriptCSS;避免重定向;图片lazyLoad能来讲讲JS的语言特性吗运行在客户端浏览器上;不用预编译,直接解析执行代码;是弱类型语言,较为灵活;与操作系统无关,跨平台的语言;脚本语言、解释性语言this的指向哪几种默认绑定:全局环境中,this默认绑定到window。隐式绑定:一般地,被直接对象所包含的函数调用时,也称为方法调用,this隐式绑定到该直接对象。隐式丢失:隐式丢失是指被隐式绑定的函数丢失绑定对象,从而默认绑定到window。显式绑定:通过call()apply()bind()方法把对象绑定到this上,叫做显式绑定。new绑定:如果函数或者方法调用之前带有关键字new,它就构成构造函数调用。对于this绑定来说,称为new绑定。【1】构造函数通常不使用return关键字,它们通常初始化新对象,当构造函数的函数体执行完毕时,它会显式返回。在这种情况下,构造函数调用表达式的计算结果就是这个新对象的值。【2】如果构造函数使用return语句但没有指定返回值,或者返回一个原始值,那么这时将忽略返回值,同时使用这个新对象作为调用结果。【3】如果构造函数显式地使用return语句返回一个对象,那么调用表达式的值就是这个对象。AngularJS双向绑定原理Angular将双向绑定转换为一堆watch表达式,然后递归这些表达式检查是否发生过变化,如果变了则执行相应的watcher函数(指view上的指令,如ngbindngshow等或是)。等到model中的值不再发生变化,也就不会再有watcher被触发,一个完整的digest循环就完成了。Angular中在view上声明的事件指令,如:ngclickngchange等,会将浏览器的事件转发给scope 上相应的 model 的响应函数。等待相应函数改变 model,紧接着触发脏检查机制刷新 view。
watch 表达式:可以是一个函数、可以是 s c o p e 上的一个属性名,也可以是一个字符串形式的表达式。 scope 上的一个属性名,也可以是一个字符串形式的表达式。 scope上的一个属性名,也可以是一个字符串形式的表达式。watch 函数所监听的对象叫做 watch 表达式。watcher 函数:指在 view上的指令(ngBind,ngShow、ngHide 等)以及{{}}表达式,他们所注册的函数。每一个 watcher 对象都包括:监听函数,上次变化的值,获取监听表达式的方法以及监听表达式,最后还包括是否需要使用深度对比(angular.equals())
什么是按需加载
当用户触发了动作时才加载对应的功能。触发的动作,是要看具体的业务场景而言,包括但不限于以下几个情况:鼠标点击、输入文字、拉动滚动条,鼠标移动、窗口大小更改等。加载的文件,可以是 JS、图片、CSS、HTML 等。
说一下什么是 virtual dom
用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中 当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异 把所记录的差异应用到所构建的真正的 DOM 树上,视图就更新了。Virtual DOM 本质上就是在 JS 和 DOM 之间做了一个缓存。

webpack 用来干什么的

webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
ant-design 优点和缺点
优点:组件非常全面,样式效果也都比较不错。
缺点:框架自定义程度低,默认 UI 风格修改困难。

JS 中继承实现的几种方式

1、原型链继承,将父类的实例作为子类的原型,他的特点是实例是子类的实例也是父类的实例,父类新增的原型方法/属性,子类都能够访问,并且原型链继承简单易于实现,缺点是来自原型对象的所有属性被所有实例共享,无法实现多继承,无法向父类构造函数传参。
2、构造继承,使用父类的构造函数来增强子类实例,即复制父类的实例属性给子类,构造继承可以向父类传递参数,可以实现多继承,通过 call 多个父类对象。但是构造继承只能继承父类的实例属性和方法,不能继承原型属性和方法,无法实现函数服用,每个子类都有父类实例函数的副本,影响性能
3、实例继承,为父类实例添加新特性,作为子类实例返回,实例继承的特点是不限制调用方法,不管是 new 子类()还是子类()返回的对象具有相同的效果,缺点是实例是父类的实例,不是子类的实例,不支持多继承
4、拷贝继承:特点:支持多继承,缺点:效率较低,内存占用高(因为要拷贝父类的属性)无法获取父类不可枚举的方法(不可枚举方法,不能使用 for in 访问到)
5、组合继承:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
6、寄生组合继承:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点
简单介绍一下 symbol
Symbol 是 ES6 的新增属性,代表用给定名称作为唯一标识,这种类型的值可以这样创建,let id=symbol(“id”)
Symbl 确保唯一,即使采用相同的名称,也会产生不同的值,我们创建一个字段,仅为知道对应 symbol 的人能访问,使用 symbol 很有用,symbol 并不是 100%隐藏,有内置方法 Object.getOwnPropertySymbols(obj)可以获得所有的 symbol。
也有一个方法 Reflect.ownKeys(obj)返回对象所有的键,包括 symbol。
SGML、HTML、XML和XHTML的区别?
1、SGML是标准通用标记语言,是一种定义电子文档结构和描述其内容的国际标准语言,是所有电子文档标记语言的起源。
2、HTML是超文本标记语言,主要是用于规定怎么显示网页。
3、XML是可扩展标记语言是未来网页语言的发展方向,XML和HTML的最大区别就在于XML的标签是可以自己创建的,数量无限多,而HHTL的标签都是固定的而且数量有限。
4、XHTML也是现在基本上所有网页都在用的标记语言,他其实和HTML没什么本质的区别,标签都一样,用法也都一样,就是比HTML更严格,比如标签必须都用小写,标签都必须有闭合标签等。
jpg和png格式的图片有什么区别?
jPg是有损压缩格式,png是无损压缩格式。所以相同的图片,jpg体积会小。比如我们一些官网的banner图,一般都很大,所以适合用jpg类型的图片。但png分8位的和24位的,8位的体积会小很多,但在某些浏览器下8位的png图片会有锯齿。
事件模型有三个常用方法:
event.stopPropagation:阻止捕获和冒泡阶段中,当前事件的进一步传播,
event.stopImmediatePropagetion,阻止调用相同事件的其他侦听器,
event.preventDefault,取消该事件(假如事件是可取消的)而不停止事件的进一步传播,
event.target:指向触发事件的元素,在事件冒泡过程中这个值不变
event.currentTarget = this,时间帮顶的当前元素,只有被点击时目标元素的 target 才会等
于 currentTarget,
setTimeout(fn,100);100 毫秒是如何权衡的
setTimeout()函数只是将事件插入了任务列表,必须等到当前代码执行完,主线程才会去执行它指定的回调函数,有可能要等很久,所以没有办法保证回调函数一定会在setTimeout 指定的时间内执行,100 毫秒是插入队列的时间+等待的时间
怎么获得对象上的属性:比如说通过 Object.key()
从 ES5 开始,有三种方法可以列出对象的属性
for(let I in obj)该方法依次访问一个对象及其原型链中所有可枚举的类型
object.keys:返回一个数组,包括所有可枚举的属性名称
object.getOwnPropertyNames:返回一个数组包含不可枚举的属性

简单讲一讲 ES6 的一些新特性

ES6 在变量的声明和定义方面增加了 let、const 声明变量,有局部变量的概念,赋值中有比较吸引人的结构赋值,同时 ES6 对字符串、 数组、正则、对象、函数等拓展了一些方法,如字符串方面的模板字符串、函数方面的默认参数、对象方面属性的简洁表达方式,ES6 也 引入了新的数据类型 symbol,新的数据结构 set 和 map,symbol 可以通过typeof 检测出来,为解决异步回调问题,引入了 promise 和 generator,还有最为吸引人了实现 Class 和模块,通过 Class 可以更好的面向对象编程,使用模块加载方便模块化编程,当然考虑到 浏览器兼容性,我们在实际开发中需要使用 babel 进行编译重要的特性:
块级作用域:ES5 只有全局作用域和函数作用域,块级作用域的好处是不再需要立即执行的函数表达式,循环体中的闭包不再有问题
rest 参数:用于获取函数的多余参数,这样就不需要使用 arguments 对象了,
promise:一种异步编程的解决方案,比传统的解决方案回调函数和事件更合理强大
模块化:其模块功能主要有两个命令构成,export 和 import,export 命令用于规定模块的
对外接口,import 命令用于输入其他模块提供的功能
 promise 和 await/async 的关系 都是异步编程的解决方案
 JS 加载过程阻塞,解决方法。
指定 script 标签的 async 属性。
如果 async=“async”,脚本相对于页面的其余部分异步地执行(当页面继续进行解析时,脚本将被执行) 如果不使用 async 且 defer=“defer”:脚本将在页面完成解析时执行
 JavaScript 中的轮播实现原理?假如一个页面上有两个轮播,你会怎么实现?
图片轮播的原理就是图片排成一行,然后准备一个只有一张图片大小的容器,对这个容器设置超出部分隐藏,在控制定时器来让这些图片整体左移或右移,这样呈现出来的效果就是图片在轮播了。如果有两个轮播,可封装一个轮播组件,供两处调用
 arguments
arguments 是类数组对象,有 length 属性,不能调用数组方法 可用 Array.from()转换

Promise

Promise 对象是 CommonJS 工作组提出的一种规范,目的是为异步编程提供统一接口。每一个异步任务返回一个 Promise 对象,该对象有一个 then 方法,允许指定回调函数。
f1().then(f2);
一个 promise 可能有三种状态:等待(pending)、已完成(resolved,又称 fulfilled)、 已拒绝(rejected)。promise 必须实现 then 方法(可以说,then 就是 promise 的核心),而且 then 必须返回一个 promise,同一个 promise 的 then 可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致。 then 方法接受两个参数,第一个参数是成功时的回调,在 promise 由“等待”态转换到 “完成”态时调用,另一个是失败时的回调,在 promise 由“等待”态转换到“拒绝”态时调用。同时,then 可以接受另一个 promise 传入,也接受一个“类 then”的对象或方法,即 thenable 对象。
JSONP 的缺点
JSON 只支持 get,因为 script 标签只能使用 get 请求; JSONP 需要后端配合返回指定格式的数据。
关于 dom 的 api 有什么
节点创建型 api,页面修改型 API,节点查询型 API,节点关系型 api,元素属性型 api, 元素样式型 api 等
active 兼容处理,即伪类:active 失效
将 :visited 放到最后,则会导致以下结果:若链接已经被访问过,a:visited 会覆盖:active 和:hover 的样式声明,链接将总是呈现为紫色。 基于此原因,上述代码必须按照顺序定义: :link — :visited — :hover — :active,为方便记忆,可记为“LOVE HATE”

Babel 的原理是什么?

babel 的转译过程也分为三个阶段,这三步具体是:
(1)解析 Parse: 将代码解析生成抽象语法树(即 AST ),即词法分析与语法分析的过程
(2)转换 Transform: 对于 AST 进行变换一系列的操作,babel 接收得到AST 并通过 babel-traverse 对其进行遍历,在此过程中进行添加、更新及移除等操作
(3)生成 Generate: 将变换后的 AST 再转换为 JS 代码, 使用到的模块是babel-generator 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_45754783

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值