文章目录
- 网络基础:
- js
- Bom(浏览器对象模型)
- 前端跨域问题的解决方案:
- **fetch 发送 2 次请求的原因**
- **Cookie、sessionStorage、localStorage 的区别**
- **说一下 web worker**
- **Cookie 如何防范 XSS 攻击**
- **Cookie 和 session 的区别**
- **一句话概括 RESTFUL**
- **讲讲 viewport 和移动端布局**
- **click 在 ios 上有 300ms 延迟,原因及如何解决?**
- **addEventListener 参数**
- js如何实现深拷贝
- **cookie 和 session 的区别,localstorage 和 sessionstorage 的区别**
- 写一个简单的观察者模式:
- 防抖节流:
- eventloop事件循环
- **补充 get 和 post 请求在缓存方面的区别**
- **说一下闭包**
- **说一下类的创建和继承**
- **如何解决异步回调地狱**
- **说说前端中的事件流**
- **说一下事件委托**
- **说一下图片的懒加载和预加载**
- **mouseover 和 mouseenter 的区别**
- **JS 的 new 操作符做了哪些事情**
- 改变函数内部 this 指针的指向函数(bind,apply,call 的区别)
- **JS 的各种位置,比如 clientHeight,scrollHeight,offsetHeight ,以及 scrollTop,** offsetTop,clientTop 的区别?
- **JS 拖拽功能的实现**
- **异步加载 JS 的方法**
- **Ajax 解决浏览器缓存问题**
- **JS 中的垃圾回收机制**
- **eval 是做什么的**
- **如何理解前端模块化**
- **说一下 CommonJS、AMD 和 CMD**
- **实现一个 once 函数,传入函数参数只执行一次**
- promise封装ajax
- HTML5
- css
- 如何画一个三角形
- 介绍一下css盒子模型
- **link 标签和 import 标签的区别**
- **transition 和 animation 的区别**
- padding撑大盒子的的解决方案
- flex布局
- BFC(块级格式化上下文)
- **多行元素的文本省略号**
- **visibility=hidden, opacity=0,display:none**
- **双边距重叠问题(外边距折叠)**
- **position 属性 比较**
- **浮动清除**
- **css3 新特性**
- calc()属性
- **z-index 的定位方法**
- **如果想要改变一个 DOM 元素的字体颜色,不在它本身上进行操作**
- **设置一个元素的背景颜色,背景颜色会填充哪些区域**
- **inline-block、inline 和 block 的区别;为什么 img 是 inline 还可以设置宽高**
- **了解重绘和重排吗,知道怎么去减少重绘和重排吗,让文档脱离文档流有** **哪些方法**
- **overflow 的原理**
- **box-sizing 的语法和基本用处**
- **两个嵌套的 div,position 都是 absolute,子 div 设置 top 属性,那么这个 top** 是相对于父元素的哪个位置定位的。
- **垂直居中**
- **了解重绘和重排吗,知道怎么去减少重绘和重排吗,让文档脱离文档流有** **哪些方法**
- **overflow 的原理**
- **box-sizing 的语法和基本用处**
- **两个嵌套的 div,position 都是 absolute,子 div 设置 top 属性,那么这个 top** 是相对于父元素的哪个位置定位的。
- **垂直居中**
网络基础:
1.https的过程
对称加密:f1(k, data) = x, f2(k,x) = data; 只有一种密钥,其密钥如果每一次传输都唯一,就是安全的,否则不安全
非对称加密:f1(pk,data) = x, f2(sk, x) = data; 有公钥和私钥,客户端对服务端是安全的,服务端给客户端传输的过程则不安全
SSL:客户端于通过CA认证的服务端使用非对称加密商讨出唯一的key,然后使用对称加密的方式进行数据传输;
http是明文传输,不安全;
2. tcp的3次握手4次挥手
3. TCP和UDP的区别
说一下http2.0
HTTP2.0大幅度的提高了web性能,在HTTP1.1完全语义兼容的基础上,进一步减少了网络的延迟。实现低延迟高吞吐量。对于前端开发者而言,减少了优化工作。本文将重点围绕以下几点新特性的作用、工作过程以及如何更出色的完成了优化工作来介绍HTTP2.0
- 二进制分帧
- 首部压缩
- 多路复用
- 请求优先级
- 服务器推送
一. 介绍
HTTP/2是HTTP协议自1999年HTTP1.1发布后的首个更新,主要基于SPDY协议。
1.1 什么是SPDY协议
SPDY是Speedy的昵音,意为“更快”。它是Google开发的基于TCP协议的应用层协议。目标是优化HTTP协议的性能,通过压缩、多路复用和优先级等技术,缩短网页的加载时间并提高安全性。SPDY协议的核心思想是尽量减少TCP连接数。SPDY并不是一种用于替代HTTP的协议,而是对HTTP协议的增强。
1.2 HTTP1.X的缺点
任何事物的更新都是为了弥补或修复上个版本的某些问题,那么我们来看看HTTP1.x都有哪些缺点以至于我们要使用HTTP2.0。
HTTP1.x有以下几个主要缺点:
- HTTP/1.0一次只允许在一个TCP连接上发起一个请求,HTTP/1.1使用的流水线技术也只能部分处理请求并发,仍然会存在队列头阻塞问题,因此客户端在需要发起多次请求时,通常会采用建立多连接来减少延迟。
- 单向请求,只能由客户端发起。
- 请求报文与响应报文首部信息冗余量大。
- 数据未压缩,导致数据的传输量大
我们可以通过一个链接来对比一下HTTP2.0到底比HTTP1.x快了多少。链接地址
二. 二进制分帧
在不改变HTTP1.x的语义、方法、状态码、URL以及首部字段的情况下,HTTP2.0是怎样突破HTTP1.1的性能限制,改进传输性能,实现低延迟高吞吐量的呢?关键之一就是在应用层(HTTP)和传输层(TCP)之间增加一个二进制分帧层。
在整理二进制分帧及其作用的时候我们先来铺垫一点关于帧的知识:
- 帧:HTTP2.0通信的最小单位,所有帧都共享一个8字节的首部,其中包含帧的长度、类型、标志、还有一个保留位,并且至少有标识出当前帧所属的流的标识符,帧承载着特定类型的数据,如HTTP首部、负荷、等等。
- 消息:比帧大的通讯单位,是指逻辑上的HTTP消息,比如请求、响应等。由一个或多个帧组成
- 流:比消息大的通讯单位。是TCP连接中的一个虚拟通道,可以承载双向的消息。每个流都有一个唯一的整数标识符
HTTP2.0中所有加强性能的核心是二进制传输,在HTTP1.x中,我们是通过文本的方式传输数据。基于文本的方式传输数据存在很多缺陷,文本的表现形式有多样性,因此要做到健壮性考虑的场景必然有很多,但是二进制则不同,只有0和1的组合,因此选择了二进制传输,实现方便且健壮。
在HTTP2.0中引入了新的编码机制,所有传输的数据都会被分割,并采用二进制格式编码。
为了保证HTTP不受影响,那就需要在应用层(HTTP2.0)和传输层(TCP or UDP)之间增加一个二进制分帧层。在二进制分帧层上,HTTP2.0会将所有传输的信息分为更小的消息和帧,并采用二进制格式编码,其中HTTP1.x的首部信息会被封装到Headers帧,而Request Body则封装到Data帧。
三. 首部压缩
HTTP1.1并不支持HTTP首部压缩,为此SPDY和HTTP2.0出现了。SPDY是用的是DEFLATE算法,而HTTP2.0则使用了专门为首部压缩设计的HPACK算法。
HTTP每次通讯(请求或响应)都会携带首部信息用于描述资源属性。
在HTTP1.0中,我们使用文本的形式传输header,在header中携带cookie的话,每次都需要重复传输几百到几千的字节,这着实是一笔不小的开销。
在HTTP2.0中,我们使用了HPACK(HTTP2头部压缩算法)压缩格式对传输的header进行编码,减少了header的大小。并在两端维护了索引表,用于记录出现过的header,后面在传输过程中就可以传输已经记录过的header的键名,对端收到数据后就可以通过键名找到对应的值。
四. 多路复用
在HTTP1.x中,我们经常会使用到雪碧图、使用多个域名等方式来进行优化,都是因为浏览器限制了同一个域名下的请求数量,当页面需要请求很多资源的时候,队头阻塞(Head of line blocking)会导致在达到最大请求时,资源需要等待其他资源请求完成后才能继续发送。
HTTP2.0中,基于二进制分帧层,HTTP2.0可以在共享TCP连接的基础上同时发送请求和响应。HTTP消息被分解为独立的帧,而不破坏消息本身的语义,交错发出去,在另一端根据流标识符和首部将他们重新组装起来。 通过该技术,可以避免HTTP旧版本的队头阻塞问题,极大提高传输性能。
五. 请求优先级
把HTTP消息分为很多独立帧之后,就可以通过优化这些帧的交错和传输顺序进一步优化性能。
六. 服务器推送
HTTP2.0新增的一个强大的新功能,就是服务器可以对一个客户端请求发送多个响应。服务器向客户端推送资源无需客户端明确的请求。
服务端根据客户端的请求,提前返回多个响应,推送额外的资源给客户端。如下图,客户端请求stream 1(/page.html)。服务端在返回stream 1的消息的同时推送了stream 2(/script.js)和stream 4(/style.css)
服务端推送是一种在客户端请求之前发送数据的机制。在HTTP2.0中,服务器可以对一个客户端的请求发送多个响应。如果一个请求是由你的主页发送的,服务器可能会响应主页内容、logo以及样式表,因为他知道客户端会用到这些东西。这样不但减轻了数据传送冗余步骤,也加快了页面响应的速度,提高了用户体验。
推送的缺点:所有推送的资源都必须遵守同源策略。换句话说,服务器不能随便将第三方资源推送给客户端,而必须是经过双方的确认才行。
补充 400 和 401、403 状态码
参考回答:
(1)400 状态码:请求无效
产生原因:
前端提交数据的字段名称和字段类型与后台的实体没有保持一致
前端提交到后台的数据应该是 json 字符串类型,但是前端没有将对象 JSON.stringify 转
化成字符串。
解决方法:
对照字段的名称,保持一致性
将 obj 对象通过 JSON.stringify 实现序列化
(2)401 状态码:当前请求需要用户验证
(3)403 状态码:服务器已经得到请求,但是拒绝执行
HTTP状态码表示客户端HTTP请求的返回结果、标记服务器端的处理是否正常或者是出现的错误,能够根据返回的状态码判断请求是否得到正确的处理很重要。
状态码由3位数字和原因短语组成,例如下图所示:
数字中的第一位指定了响应类别,后两位无分类,响应类别有一下5种:
各类别常见状态码:
2xx (3种)
200 OK:表示从客户端发送给服务器的请求被正常处理并返回;
204 No Content:表示客户端发送给客户端的请求得到了成功处理,但在返回的响应报文中不含实体的主体部分(没有资源可以返回);
206 Patial Content:表示客户端进行了范围请求,并且服务器成功执行了这部分的GET请求,响应报文中包含由Content-Range指定范围的实体内容。
3xx (5种)
301 Moved Permanently:永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL;
302 Found:临时性重定向,表示请求的资源被分配了新的URL,希望本次访问使用新的URL;
301与302的区别:前者是永久移动,后者是临时移动(之后可能还会更改URL)
303 See Other:表示请求的资源被分配了新的URL,应使用GET方法定向获取请求的资源;
302与303的区别:后者明确表示客户端应当采用GET方式获取资源
304 Not Modified:表示客户端发送附带条件(是指采用GET方法的请求报文中包含if-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since中任一首部)的请求时,服务器端允许访问资源,但是请求为满足条件的情况下返回改状态码;
307 Temporary Redirect:临时重定向,与303有着相同的含义,307会遵照浏览器标准不会从POST变成GET;(不同浏览器可能会出现不同的情况);
4xx (4种)
400 Bad Request:表示请求报文中存在语法错误;
401 Unauthorized:未经许可,需要通过HTTP认证;
403 Forbidden:服务器拒绝该次访问(访问权限出现问题)
404 Not Found:表示服务器上无法找到请求的资源,除此之外,也可以在服务器拒绝请求但不想给拒绝原因时使用;
5xx (2种)
500 Inter Server Error:表示服务器在执行请求时发生了错误,也有可能是web应用存在的bug或某些临时的错误时;
503 Server Unavailable:表示服务器暂时处于超负载或正在进行停机维护,无法处理请求;
强缓存、协商缓存什么时候用哪个
强缓存和协商缓存是http缓存中不同的两种思路,用哪种缓存体现在respone header 的cache-control,常见的设置是max-age public private no-cache no-store等。
max-age用来设置过期时限,是一个以秒为单位的滑动时间
public是代理服务器和客户端都缓存
private就是客户端本地缓存
no-cache 跳过设置强缓存,但是不妨碍设置协商缓存;一般如果你做了强缓存,只有在强缓存失效了才走协商缓存的,设置了no-cache就不会走强缓存了,每次请求都回询问服务端
no-store是不使用缓存
强缓存:
是直接设置缓存有效期,不过期就不发送请求,过期了再发送请求,优势就是对服务器的压力比较小,响应比较快,但是缺点就是有可能当服务器资源发生更改的时候,不能及时的更新。
协商缓存:
也是有有效期限的,但是每次调用缓存资源之前都会向服务器发送请求,服务器资源如果没有发生更改,就返回状态码304,客户端看到304就去缓存中直接调用资源,如果服务端的资源发生改变了,就给客户端就返回资源。
Etag
Etag是对last-modified的补充,last-modified通过对比修改时间戳来判断是不是给客户端返回资源。
last-modified有一些问题:
1、如果对资源的操作没有改变其内容,比如增加了什么内容后又将增加的内容删除,会导致修改时间戳改变,而内容并没有改变,这时发起请求,服务端不会返回304,而是返回资源给客户端
2、时间戳只能把时间精确到秒,如果修改资源内容的时候在一秒内完成操作,服务端就会返回304
Etag补充了lost-modified上述的不足,Etag对服务端资源的内容进行哈希计算生成一个字符串,作为内容指纹,内容发生改变时就返回资源,如果内容不改变,就返回304
Etag也存在一些问题 :
Etag需要对资源内容进行计算,如果资源很大会加重服务器负担,拖慢响应的速度。
Etag字段值的生成分为强验证和弱验证,强验证对比前后资源的每一个字节,弱验证则只验证资源的关键特征
前端性能优化
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1MhEIazc-1648643525693)(C:\Users\blackcatkiller\AppData\Roaming\Typora\typora-user-images\image-20220317195935175.png)]
性能评判指标:
最大内容绘制、首次输入延迟、内容布局稳定性
性能测试工具:
lightHouse(灯塔)
WebPageTest(线上性能测试,支持不同地区节点的性能测试)
线程与进程
一般一个应用是一个进程,一个进程里有多个线程
早期的浏览器是单进程浏览器,一个页面的崩溃会导致整个浏览器的进程都出现问题
chrome浏览器是多进程浏览器
建立Http请求:
DNS解析:
关键渲染路径
构建对象模型
请求和响应优化:
dns相关
http长链接:
http2
http1.1是串行响应,http2可以并发响应
在地址栏里输入一个 URL,到这个页面呈现出来,中间会发生什么?
xss与csrf攻击
xss
XSS其实就是Html的注入问题,攻击者的输入没有经过严格的控制进入了数据库,最终显示给来访的用户,导致可以在来访用户的浏览器里以浏览用户的身份执行Html代码,数据流程如下:攻击者的Html输入—>web程序—>进入数据库—>web程序—>用户浏览器。
检测方法:过滤检测用户提交的表单数据,对敏感字符串进行过滤 或者处理,防止它被当作js脚本运行
避免:使用HTTP头指定类型,比如Content-Type
crf
XSS 是实现 CSRF 的诸多途径中的一条,但绝对不是唯一的一条。一般习惯上把通过 XSS 来实现的 CSRF 称为 XSRF。
CSRF 顾名思义,是伪造请求,冒充用户在站内的正常操作。我们知道,绝大多数网站是通过 cookie 等方式辨识用户身份(包括使用服务器端 Session 的网站,因为 Session ID 也是大多保存在 cookie 里面的),再予以授权的。所以要伪造用户的正常操作,最好的方法是通过 XSS 或链接欺骗等途径,让用户在本机(即拥有身份 cookie 的浏览器端)发起用户所不知道的请求。
要完成一次CSRF攻击,受害者必须依次完成两个步骤:
1.登录受信任网站A,并在本地生成Cookie。
2.在不登出A的情况下,访问危险网站B。
看到这里,你也许会说:“如果我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:
1.你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站。
2.你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了……)
3.上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。
上面大概地讲了一下CSRF攻击的思想,下面我将用几个例子详细说说具体的CSRF攻击,这里我以一个银行转账的操作作为例子(仅仅是例子,真实的银行网站没这么傻:>)
事件循环
https://www.cnblogs.com/yugege/p/9598265.html
js
Bom(浏览器对象模型)
window对象:
window 是客户端浏览器对象模型的基类,window 对象是客户端 JavaScript 的全局对象。一个 window 对象实际上就是一个独立的窗口,对于框架页面来说,浏览器窗口每个框架都包含一个 window 对象。
在客户端浏览器中,window 对象是访问 BOM 的接口,如引用 document 对象的 document 属性,引用自身的 window 和 self 属性等。同时 window 也为客户端 JavaScript 提供全局作用域。
navigator对象:
navigator 对象存储了与浏览器相关的基本信息,如名称、版本和系统等。通过 window.navigator 可以引用该对象,并利用它的属性来读取客户端基本信息。
浏览器检测:
location对象
location 对象存储了当前文档位置(URL)相关的信息,简单地说就是网页地址字符串。使用 window 对象的 location 属性可以访问。
history对象:
history 对象存储了库互动浏览器的浏览历史,通过 window 对象的 history 属性可以访问该对象,实际上 history 属性仅存储最近访问的、有限条目的 URL 信息。
在 HTML5 之前,为了保护客户端浏览信息的安全和隐私,history 对象禁止 JavaScript 脚本直接操作这些访问信息。不过 HTML5 新增了一个 History API,该 API 允许用户通过 JavaScript 管理浏览器的历史记录,实现无刷新更改浏览器地址栏的地址,配合 History + Ajax 可以设计不需要刷新页面的跳转。
属性:
方法:
screen对象
前端跨域问题的解决方案:
什么是跨域?
跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的。
广义的跨域:
1.) 资源跳转: A链接、重定向、表单提交
2.) 资源嵌入: <link>、<script>、<img>、<frame>等dom标签,还有样式中background:url()、@font-face()等文件外链
3.) 脚本请求: js发起的ajax请求、dom和js对象的跨域操作等
其实我们通常所说的跨域是狭义的,是由浏览器同源策略限制的一类请求场景。
什么是同源策略?
同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
同源策略限制以下几种行为:
1.) Cookie、LocalStorage 和 IndexDB 无法读取
2.) DOM 和 Js对象无法获得
3.) AJAX 请求不能发送
fetch 发送 2 次请求的原因
跨域请求就会出源现这样的问题。
由于CORS(cross origin resource share)规范的存在,浏览器会首先发送知一次options嗅探,同时header带上origin,判断是否道有跨域请求权限,服务器响应access control allow origin的值,供浏览器与origin匹配,如果匹配则正式发送post请求。
所有跨域的js在提交post请求的时候,如果服务端设置了可跨域访问
public static function setCrossDomain()
{
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
header('Access-Control-Allow-Methods: GET, POST, PUT');
}
都会默认发送两次请求,第一次是预检请求,查询是否支持跨域,第二次才是真正的post提交。
JS中出现这个现象原因在于你发送了一个非简单请求。
简单请求与非简单请求:
* 请求方式:HEAD,GET,POST
* 请求头信息:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type 对应的值是以下三个中的任意一个
application/x-www-form-urlencoded
multipart/form-data
text/plain
只有同时满足以上两个条件时,才是简单请求,否则为非简单请求
解决方法:
由上面定义可以看出,把你的post提交改成get提交,就不会两次请求,或者将post的header改成application/x-www-form-urlencoded, multipart/form-data 或 text/plain中的一种
Cookie、sessionStorage、localStorage 的区别
说一下 web worker
https://www.ruanyifeng.com/blog/2018/07/web-worker.html
Cookie 如何防范 XSS 攻击
XSS(跨站脚本攻击)是指攻击者在返回的 HTML 中嵌入 javascript 脚本,为了减轻这些 攻击,需要在 HTTP 头部配上,set-cookie:
httponly-这个属性可以防止 XSS,它会禁止 javascript 脚本来访问 cookie。
secure - 这个属性告诉浏览器仅在请求为 https 的时候发送 cookie。
结果应该是这样的:Set-Cookie=…
response.setHeader("Set-Cookie", "cookiename=httponlyTest;Path=/;Domain=domainvalue;Max-Age=seconds;HTTPOnly");
Cookie 和 session 的区别
https://www.cnblogs.com/l199616j/p/11195667.html
一句话概括 RESTFUL
就是用 URL 定位资源,用 HTTP 描述操作。
讲讲 viewport 和移动端布局
https://github.com/forthealllight/blog/issues/13
click 在 ios 上有 300ms 延迟,原因及如何解决?
addEventListener 参数
addEventListener(event, function, useCapture)
其中,event 指定事件名;function 指定要事件触发时执行的函数;useCapture 指定事件
是否在捕获或冒泡阶段执行。
js如何实现深拷贝
递归实现
//使用递归的方式实现数组、对象的深拷贝
function deepClone1(obj) {
//判断拷贝的要进行深拷贝的是数组还是对象,是数组的话进行数组拷贝,对象的话进行对象拷贝
var objClone = Array.isArray(obj) ? [] : {};
//进行深拷贝的不能为空,并且是对象或者是
if (obj && typeof obj === "object") {
for (key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] && typeof obj[key] === "object") {
objClone[key] = deepClone1(obj[key]);
} else {
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
json对象实现深拷贝
//通过js的内置对象JSON来进行数组对象的深拷贝
function deepClone2(obj) {
var _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone;
}
Object.assign()拷贝
对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对相中有对象的时候,此方法再二级属性以后就是浅拷贝。
lodash函数库实现深拷贝
lodash很热门的函数库,提供了 lodash.cloneDeep()实现深拷贝
cookie 和 session 的区别,localstorage 和 sessionstorage 的区别
写一个简单的观察者模式:
一个被观察者可以被很多的观察者绑定,当被观察者的重要状态发生改变的时候,就通知观察者,观察者就会进行相应的更新。
我对观察者模式的理解是这样的:前端常见的观察者模式其实就是事件监听,当我们给dom元素绑定点击事件的时候,dom元素就是观察者,鼠标是被观察者,
class Sub{
constructor(){
this.observers = [];
this.state = '初始状态';
}
getState(){
return this.state;
}
setState(state){
this.state = state;
this.notify();//通知观察者
}
attach(observer){//新增观察者
this.observers.push(observer);
}
notify(){
this.observers.forEach(observer => observer.update(this.state))
}
}
class Observer{
constructor(name,sub){
this.name = name;
this.sub = sub;
this.sub.attach(this)
}
update(state){
console.log(`观察者${this.name}收到状态${state}`)
}
}
const sub = new Sub();
const o1 = new Observer('o1',sub);
sub.setState('hahaha');
防抖节流:
防抖是说,一段时间内重复触发,只执行最后一次
const antiShake = (fn,delay)=>{
let timer = null;//利用闭包
return function(){
if (timer){
clearTimeout(timer);
}
timer = setTimeout(fn,delay);
}
}
节流是说,每次触发执行后,让目标函数失效一段时间,
const throttle = (fn,delay)=>{
let valid = true
return function() {
if(!valid){
//休息时间 暂不接客
return false
}
// 工作时间,执行函数并且在间隔期内把状态位设为无效
valid = false
fn()
setTimeout(() => {
valid = true;
}, delay)
}
}
eventloop事件循环
主线程->微任务->宏任务
补充 get 和 post 请求在缓存方面的区别
post/get 的请求区别,具体不再赘述。
补充补充一个 get 和 post 在缓存方面的区别:
get 请求类似于查找的过程,用户获取数据,可以不用每次都与数据库连接,所以可以
使用缓存。
post 不同,post 做的一般是修改和删除的工作,所以必须与数据库交互,所以不能使用
缓存。因此 get 请求适合于请求缓存。
说一下闭包
一句话可以概括:闭包就是能够读取其他函数内部变量的函数,或者子函数在外调用,
子函数所在的父函数的作用域不会被释放。
应用:防抖节流函数的封装
说一下类的创建和继承
(1)类的创建(es5):new 一个 function,在这个 function 的 prototype 里面增加属性和 方法
// 定义一个动物类
function Animal (name) {
// 属性
this.name = name || 'Animal';
// 实例方法
this.sleep = function(){
console.log(this.name + '正在睡觉!');
}
}
// 原型方法
Animal.prototype.eat = function(food) {
console.log(this.name + '正在吃:' + food); };
这样就生成了一个 Animal 类,实力化生成对象后,有方法和属性。
(2)类的继承——原型链继承
function Cat(){ }
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.eat('fish'));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true
介绍:在这里我们可以看到 new 了一个空对象,这个空对象指向 Animal 并且 Cat.prototype 指向了这个空对象,这种就是基于原型链的继承。
特点:基于原型链,既是父类的实例,也是子类的实例
缺点:无法实现多继承
(3)构造继承:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给 子类(没用到原型)
function Cat(name){
Animal.call(this);
this.name = name || 'Tom';
}
// TestCode
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
特点:可以实现多继承
缺点:只能继承父类实例的属性和方法,不能继承原型上的属性和方法。
(4)实例继承和拷贝继承
实例继承:为父类实例添加新特性,作为子类实例返回
拷贝继承:拷贝父类元素上的属性和方法
上述两个实用性不强,不一一举例。
(5)组合继承:相当于构造继承和原型链继承的组合体。通过调用父类构造,继承父 类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
function Cat(name){
Animal.call(this);
this.name = name || 'Tom';
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true
特点:可以继承实例属性/方法,也可以继承原型属性/方法
缺点:调用了两次父类构造函数,生成了两份实例
如何解决异步回调地狱
promise、generator、async/await
说说前端中的事件流
HTML 中与 javascript 交互是通过事件驱动来实现的,例如鼠标点击事件 onclick、页面 的滚动事件 onscroll 等等,可以向文档或者文档中的元素添加事件侦听器来预订事件。
想要知道这些事件是在什么时候进行调用的,就需要了解一下“事件流”的概念。
什么是事件流:事件流描述的是从页面中接收事件的顺序,DOM2 级事件流包括下面几个
阶段。
事件捕获阶段 :document-》目标元素
处于目标阶段
事件冒泡阶段 :目标元素-》document
addEventListener:addEventListener 是 DOM2 级事件新增的指定事件处理程序的操作, 这个方法接收 3 个参数:
要处理的事件名、作为事件处理程序的函数和一个布尔值。最
后这个布尔值参数如果是 true,表示在捕获阶段调用事件处理程序;如果是 false,表示
在冒泡阶段调用事件处理程序。
IE 只支持事件冒泡。
说一下事件委托
简介:事件委托指的是,不在事件的发生地(直接 dom)上设置监听函数,而是在其父 元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判 断事件发生元素 DOM 的类型,来做出不同的响应。
举例:最经典的就是 ul 和 li 标签的事件监听,比如我们在添加事件时候,采用事件委 托机制,不会在 li 标签上直接添加,而是在 ul 父元素上添加。
好处:比较合适动态元素的绑定,新添加的子元素也会有监听函数,也可以有事件触发 机制。
说一下图片的懒加载和预加载
预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染。
懒加载:懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数。
两种技术的本质:两者的行为是相反的,一个是提前加载,一个是迟缓甚至不加载。
懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力
mouseover 和 mouseenter 的区别
mouseover:当鼠标移入元素或其子元素都会触发事件,所以有一个重复触发,冒泡的过 程。对应的移除事件是 mouseout
mouseenter:当鼠标移除元素本身(不包含元素的子元素)会触发事件,也就是不会冒 泡,对应的移除事件是 mouseleave
JS 的 new 操作符做了哪些事情
new 操作符新建了一个空对象,这个对象原型指向构造函数的 prototype,执行构造函数
后返回这个对象。
改变函数内部 this 指针的指向函数(bind,apply,call 的区别)
通过 apply 和 call 改变函数的 this 指向,他们两个函数的第一个参数都是一样的表示要 改变指向的那个对象,第二个参数,apply 是数组,而 call 则是 arg1,arg2…这种形式。通 过 bind 改变 this 作用域会返回一个新的函数,这个函数不会马上执行。
JS 的各种位置,比如 clientHeight,scrollHeight,offsetHeight ,以及 scrollTop, offsetTop,clientTop 的区别?
clientHeight:表示的是可视区域的高度,不包含 border 和滚动条
offsetHeight:表示可视区域的高度,包含了 border 和滚动条
scrollHeight:表示了所有区域的高度,包含了因为滚动被隐藏的部分。
clientTop:表示边框 border 的厚度,在未指定的情况下一般为 0
scrollTop: 代表在有滚动条时,滚动条向下滚动的距离也就是元素顶部被遮住部分的高度。在没有滚动条时scrollTop==0恒成立。单位px,可读可设置
offsetTop: 当前元素顶部距离最近父元素顶部的距离,和有没有滚动条没有关系。单位px,只读元素。
JS 拖拽功能的实现
首先是三个事件,分别是 mousedown,mousemove,mouseup
当鼠标点击按下的时候,需要一个 tag 标识此时已经按下,可以执行 mousemove 里面的
具体方法。
clientX,clientY 标识的是鼠标的坐标,分别标识横坐标和纵坐标,并且我们用 offsetX
和 offsetY 来表示元素的元素的初始坐标,移动的举例应该是:
鼠标移动时候的坐标-鼠标按下去时候的坐标。
也就是说定位信息为:
鼠标移动时候的坐标-鼠标按下去时候的坐标+元素初始情况下的 offetLeft.
还有一点也是原理性的东西,也就是拖拽的同时是绝对定位,我们改变的是绝对定位条
件下的 left
以及 top 等等值。
补充:也可以通过 html5 的拖放(
Drag 和 drop来实现:
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
body{
margin:0;
position: relative;
height:100vh;
}
#obj{
position: absolute;
left:0;
top:0;
height:100px;
width:100px;
background-color:red;
}
#obj:hover{
cursor:pointer;
}
</style>
</head>
<body>
<div id="obj" draggable="true"></div>
</body>
<script >
let obj = document.querySelector('#obj');
console.log(obj);
obj.ondragstart = function(e) {
console.log('开始拖动');
offsetX = e.offsetX;//鼠标相对于被拖动元素左上角的坐标
offsetY = e.offsetY;
}
obj.ondrag = function(e) {
x = e.clientX;//鼠标相对于可视区左上角的坐标
y = e.clientY;
if(x===0||y===0) return;//结尾时候鼠标坐标会突变为0
obj.style.left = x-offsetX+ 'px';
obj.style.top = y-offsetY+ 'px';
}
obj.ondragend = function(e) {
console.log('结束拖动')
}
</script>
</html>
异步加载 JS 的方法
defer:只支持 IE 如果您的脚本不会改变文档的内容,可将 defer 属性加入到
async,HTML5 属性仅适用于外部脚本,并且如果在 IE 中,同时存在 defer 和 async,那 么 defer 的优先级比较高,脚本将在页面完成时执行。
创建 script 标签,插入到 DOM 中
Ajax 解决浏览器缓存问题
在 ajax 发送请求前加上 anyAjaxObj.setRequestHeader(“If-Modified-Since”,“0”)。
在 ajax 发送请求前加上 anyAjaxObj.setRequestHeader(“Cache-Control”,“no-cache”)。
在 URL 后面加上一个随机数: “fresh=” + Math.random()。
在 URL 后面加上时间搓:“nowtime=” + new Date().getTime()。
如果是使用 jQuery,直接这样就可以了 $.ajaxSetup({cache:false})。这样页面的所有 ajax
都会执行这条语句就是不需要保存缓存记录。
JS 中的垃圾回收机制
eval 是做什么的
它的功能是将对应的字符串解析成 JS 并执行,应该避免使用 JS,因为非常消耗性能(2 次,一次解析成 JS,一次执行)
如何理解前端模块化
前端模块化就是复杂的文件编程一个一个独立的模块,比如 JS 文件等等,分成独立的 模块有利于重用(复用性)和维护(版本迭代),这样会引来模块之间相互依赖的问题, 所以有了 commonJS 规范,AMD,CMD 规范等等,以及用于 JS 打包(编译等处理)的 工具 webpack
说一下 CommonJS、AMD 和 CMD
https://baijiahao.baidu.com/s?id=1722161288040136664&wfr=spider&for=pc
实现一个 once 函数,传入函数参数只执行一次
function once(func) {
let tag = true;
return function () {
if (tag == true) {
func.apply(null, arguments);
tag = false;
}
return undefined;
}
}
function func(name) {
console.log(name)
}
let test = once(func);
test('abc');
test('def');
promise封装ajax
var ajax = function (url) {
return new Promise(
function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('get', url);
xhr.send(data);
xhr.onreadystatechange = function () {
if (xhr.status == 200 && readyState == 4) {
var json = JSON.parse(xhr.responseText);
resolve(json)
} else if (xhr.readyState == 4 && xhr.status != 200) {
reject('error');
}
}
}
)
}
HTML5
说一下html5 drag api
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
body{
margin:0;
position: relative;
height:100vh;
}
#obj{
position: absolute;
left:0;
top:0;
height:100px;
width:100px;
background-color:red;
}
#obj:hover{
cursor:pointer;
}
</style>
</head>
<body>
<div id="obj" draggable="true"></div>
</body>
<script >
let obj = document.querySelector('#obj');
console.log(obj);
obj.ondragstart = function(e) {
console.log('开始拖动');
offsetX = e.offsetX;
offsetY = e.offsetY;
}
obj.ondrag = function(e) {
x = e.clientX;
y = e.clientY;
if(x===0||y===0) return;
obj.style.left = x-offsetX+ 'px';
obj.style.top = y-offsetY+ 'px';
}
obj.ondragend = function(e) {
console.log('结束拖动')
}
</script>
</html>
dragapi在react中的使用:
React DnD拖放库
对 HTML 语义化标签的理解
HTML5 语义化标签是指正确的标签包含了正确的内容,结构良好,便于阅读,比如 nav 表示导航条,类似的还有 article、header、footer 等等标签。
iframe 是什么?有什么缺点?
定义:iframe 元素会创建包含另一个文档的内联框架
提示:可以将提示文字放在之间,来提示某些不支持 iframe 的浏览器
缺点:
会阻塞主页面的 onload 事件
搜索引擎无法解读这种页面,不利于 SEO
iframe 和主页面共享连接池,而浏览器对相同区域有限制所以会影响性能。
Doctype 作用?严格模式与混杂模式如何区分?它们有何意义?
Doctype 声明于文档最前面,告诉浏览器以何种方式来渲染页面,这里有两种模式,严 格模式和混杂模式。
严格模式 的排版和 JS 运作模式是 以该浏览器支持的最高标准运行。
混杂模式,向后兼容,模拟老式浏览器,防止浏览器无法兼容页面。
html5新增的元素
css
如何画一个三角形
用border来画
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
div{
width:0px;
height:0px;
border-top:100px solid black;
border-right:100px solid transparent;
border-bottom: 100px solid transparent;
border-left: 100px solid transparent;
}
</style>
<body>
<div></div>
</body>
</html>
介绍一下css盒子模型
link 标签和 import 标签的区别
transition 和 animation 的区别
Animation 和 transition 大部分属性是相同的,他们都是随时间改变元素的属性值,他们 的主要区别是 transition 需要触发一个事件才能改变属性,而 animation 不需要触发任何 事件的情况下才会随时间改变属性值,并且 transition 为 2 帧,从 from … to,而 animation 可以一帧一帧的。
padding撑大盒子的的解决方案
设置box-sizing的值为border-box
flex布局
BFC(块级格式化上下文)
overflow可以设置为hidden
多行元素的文本省略号
1display: -webkit-box
2-webkit-box-orient:vertical
3-webkit-line-clamp:3
4overflow:hidden
visibility=hidden, opacity=0,display:none
opacity=0,该元素隐藏起来了,但不会改变页面布局,并且,如果该元素已经绑定一些
事件,如 click 事件,那么点击该区域,也能触发点击事件的 visibility=hidden,该元素
隐藏起来了,但不会改变页面布局,但是不会触发该元素已经绑定的事件 display=none,
把元素隐藏起来,并且会改变页面布局,可以理解成在页面中把该元素删除掉一样。
双边距重叠问题(外边距折叠)
多个相邻(兄弟或者父子关系)普通流的块元素垂直方向 marigin 会重叠
折叠的结果为:
两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。
两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。
两个外边距一正一负时,折叠结果是两者的相加的和。
position 属性 比较
sticky定位:
是static定位和fix定位的结合,需要结合一个fix定位属性使用,如left:100px,当左边距大于100px是,采用static默认定位,当页面发生滚动,导致左边距不足100px时,就会变成fix定位。
浮动清除
https://blog.csdn.net/h_qingyi/article/details/81269667
css3 新特性
开放题。CSS3 边框如 border-radius,box-shadow 等;CSS3 背景如 background-size,
background-origin 等;CSS3 2D,3D 转换如 transform 等;CSS3 动画如 animation 等。
参考 https://www.cnblogs.com/xkweb/p/5862612.html
calc()属性
display:table 和本身的 table 有什么区别
z-index 的定位方法
z-index 属性设置元素的堆叠顺序,拥有更好堆叠顺序的元素会处于较低顺序元素之前,
z-index 可以为负,且 z-index 只能在定位元素上奏效,该属性设置一个定位元素沿 z 轴的位置
,如果为正数,离用户越近,为负数,离用户越远,它的属性值有 auto,默认,
堆叠顺序与父元素相等,number,inherit,从父元素继承 z-index 属性的值
如果想要改变一个 DOM 元素的字体颜色,不在它本身上进行操作
可以更改父元素的 color
设置一个元素的背景颜色,背景颜色会填充哪些区域
background-color 设置的背景颜色会填充元素的 content、padding、border 区域。
inline-block、inline 和 block 的区别;为什么 img 是 inline 还可以设置宽高
Block 是块级元素,其前后都会有换行符,能设置宽度,高度,margin/padding 水平垂直
方向都有效。
Inline:设置 width 和 height 无效,margin 在竖直方向上无效,padding 在水平方向垂直
方向都有效,前后无换行符
Inline-block:能设置宽度高度,margin/padding 水平垂直方向 都有效,前后无换行符
了解重绘和重排吗,知道怎么去减少重绘和重排吗,让文档脱离文档流有 哪些方法
overflow 的原理
要讲清楚这个解决方案的原理,首先需要了解块格式化上下文,A block formatting context is a part of a visual CSS rendering of a Web page. It is the region in which the layout of block boxes occurs and in which floats interact with each other.翻译过来就是块格式化上下文是 CSS 可视化渲染的一部分,它是一块区域,规定了内部块盒 的渲染方式,以及浮动相 互之间的影响关系
当元素设置了 overflow 样式且值不为 visible 时,该元素就构建了一个 BFC,BFC 在计算 高度时,内部浮动元素的高度也要计算在内,也就是说技术 BFC 区域内只有一个浮动 元素,BFC 的高度也不会发生塌缩,所以达到了清除浮动的目的。
box-sizing 的语法和基本用处
两个嵌套的 div,position 都是 absolute,子 div 设置 top 属性,那么这个 top 是相对于父元素的哪个位置定位的。
margin 的外边缘
垂直居中
父元素固定宽高,利用定位及设置子元素 margin 值为自身的一半。
父元素固定宽高,子元素设置 position: absolute,margin:auto 平均分配 margin
css3 属性 transform。子元素设置 position: absolute; left: 50%; top: 50%;transform:
translate(-50%,-50%);即可。
将父元素设置成 display: table, 子元素设置为单元格 display: table-cell。
弹性布局 display: flex。设置 align-items: center; justify-content: center;
Block 是块级元素,其前后都会有换行符,能设置宽度,高度,margin/padding 水平垂直
方向都有效。
Inline:设置 width 和 height 无效,margin 在竖直方向上无效,padding 在水平方向垂直
方向都有效,前后无换行符
Inline-block:能设置宽度高度,margin/padding 水平垂直方向 都有效,前后无换行符
[外链图片转存中…(img-BNNYPnVb-1648643525912)]
[外链图片转存中…(img-qHIrOJJH-1648643525916)]
了解重绘和重排吗,知道怎么去减少重绘和重排吗,让文档脱离文档流有 哪些方法
[外链图片转存中…(img-5ld1KOE0-1648643525918)]
overflow 的原理
要讲清楚这个解决方案的原理,首先需要了解块格式化上下文,A block formatting context is a part of a visual CSS rendering of a Web page. It is the region in which the layout of block boxes occurs and in which floats interact with each other.翻译过来就是块格式化上下文是 CSS 可视化渲染的一部分,它是一块区域,规定了内部块盒 的渲染方式,以及浮动相 互之间的影响关系
当元素设置了 overflow 样式且值不为 visible 时,该元素就构建了一个 BFC,BFC 在计算 高度时,内部浮动元素的高度也要计算在内,也就是说技术 BFC 区域内只有一个浮动 元素,BFC 的高度也不会发生塌缩,所以达到了清除浮动的目的。
box-sizing 的语法和基本用处
[外链图片转存中…(img-IcTKgPgm-1648643525921)]
两个嵌套的 div,position 都是 absolute,子 div 设置 top 属性,那么这个 top 是相对于父元素的哪个位置定位的。
margin 的外边缘
垂直居中
父元素固定宽高,利用定位及设置子元素 margin 值为自身的一半。
父元素固定宽高,子元素设置 position: absolute,margin:auto 平均分配 margin
css3 属性 transform。子元素设置 position: absolute; left: 50%; top: 50%;transform:
translate(-50%,-50%);即可。
将父元素设置成 display: table, 子元素设置为单元格 display: table-cell。
弹性布局 display: flex。设置 align-items: center; justify-content: center;