社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
###Vue部分
https://zhuanlan.zhihu.com/p/111310865
节流技术是用于设定在固定事件内,执行特定的功能代码,如果同一单位事件内某事件被多次触发,那么只有一次生效(节流可以用在scroll函数的事件监听上,通过事件节流来降低事件调用的频率)
1.防抖的实现
//防抖的实现
function debounce(fun, wait) {
let timer = null;
//所以下面的匿名函数适应的函数外部的变量,这里是闭包的作用
return function () {
//清空计时器是为了当事件又被触发时,重新计时
clearInterval(timer)
timer = setInterval(() => {
fun.apply(this)
}, wait)
}
}
var result = debounce(fun1, 1000)
result()
2.节流的实现
function limtfun(fun, wait) {
var perTime = 0;
return function () {
var nowTime = new Date()
if (nowTime - perTime > wait) {
fun.call(this)
perTime = nowTime//由于闭包的原因,这里的nowTime不会被清空
}
}
}
JS在执行的过程中会产生一个执行环境,js的代码在这个执行环境中按顺序执行,当遇到异步代码时,会被挂起到事件队列中(Task),对于这个队列中的任务则会涉及到微任务和宏任务,当执行栈的为空时,由于事件循环机制,就会从事件队列中拿出需要执行的代码到执行栈中执行,此时执行的循序时先执行微任务,当微任务执行完毕之后,再执行宏任务。
1)语法
var obj=new Object()
obj instanceof Object //true
2)底层原理
function myInstanceof(left, right) {
left = left.__proto__;
right = right.prototype;
while (true) {
if (left === null || left === undefined) {
return false
}
if (left === right) {
return true
}
//即上面均不满足时,继续往原型链上查找
left = left.__proto__;
}
}
参考文章:https://zhuanlan.zhihu.com/p/105487552
function jsonp(url, data, callback) {
//产出随机的回调函数名(因为可能有多个请求,这里可以区别开来)
var funcName = 'jsonp_' + Date.now() + Math.random().toString().substr(2, 5);
//如果存在其他传入参数,需要进行拼接
if (typeof data === 'object') {
var tempArr = [];
for (var key in data) {
var value = data[key];
tempArr.push(key + '=' + value)
}
//将数组以&拼接成字符串,如name=h$age=21
data = tempArr.join('&')
}
var script = document.createElement('script')
script.src = url + '?' + data + 'callback=' + funcName
document.body.appendChild(script);
//这里得到请求的数据,在回调函数中执行处理
window[funcName] = function (data) {
callback(data)
}
}
//使用
jsonp('http:127.0.0.1:3000/api', {}, function (res) {
console.log(res)
})
参考文章:
https://blog.csdn.net/weixin_40483654/article/details/106434990
实现存储功能:Cookie、localStorage、sessionStorage、indexDB
特性 | Cookie | localStroage | sessionStorage | indexDB |
---|---|---|---|---|
数据生命周期 | 一般由服务器生成,可以设置过期事件 | 除非被清理,否则一直存在 | 页面关闭时就被清理 | 除非被清理,否则一直存在 |
数据存储大小 | 4kb | 5mb | 5mb | 无限 |
与服务端的通信 | 会一直携带在请求头 | 不参与下 | 不参与 | 不参与 |
PS:没有大量的数据需求的话,可以使用localStorage和sessionStorage,对于不怎么改变的数据,尽量使用localStorage。
接下来我们将通过以下几个方面来探讨浏览器的缓存机制
我知道的浏览器的缓存位置有Service Worker、网络请求,并且有各自的优先级,当一次查找缓存并且都没有命中的时候,才会请求网络。
通常浏览器的缓存策略可以分为两种:强缓存和协商缓存。并且这两种缓存策略都是通过设置 HTTP Header 来实现的
1)强缓存(有两种设置方式)
Expires:缓存受限于本地的时间
Cache-Control:通过max-age来设置缓存的时间期限
2)协商缓存(两种设置方式)
简单的说,如果缓存过了,就需要发起请求验证资源是否更新。即当浏览器发送请求验证时,如果资源没有发生改变,那么服务器就返回304状态码,并更新浏览器的缓存有效期。(相当于浏览器和服务器进行协商,是否返回新的数据)
Last-Modified
Last-Modified表示本地文件最后修改日期,当 Last-Modified的值发送给服务器,循环服务器在该日期后资源是否有变更,有则返回新的资源,否则返回304状态码
ETag
当ETag的值发送给服务器,询问该资源是否有更新,有则返回新的资源(并且ETag的资源比Last-Modified高)
一般来说,现在都会使用工具来打包代码,那么我们可以对文件名进行哈希处理,只有当代码修改之后生产新的文件名。基于此,我们就可以给代码设置缓存有效期一年Cache-Control:max-age=3153600,这样只有html文件中引入的文件名发生了改变,才回去下载新的代码,否则就一直使用缓存。
虚拟滚动:原理时只渲染可视区域内的内容,非可视区的则不渲染,当用户在滚动的时候就实时去替换渲染的内容。
我们知道,在浏览器的渲染线程和JS引擎线程时互斥的,因此在渲染时,若遇到script标签时,则此时会渲染会停止下来,等待script代码加载完毕,再从暂停的地方重新渲染。也就是说,当你想首屏渲染越快,那么就不应该再首屏加载js文件,也就是建议将script标签放在body标签底部的原因。当然,你也可以给script标签添加defer或者async属性,那么此时的script可以放在任意位置,因为此时js文件会并行下载,若时defer,会等待页面渲染结束才执行,而async会在加载完毕之后立即执行。
只是defer和async表示js文件的加载和解析不会阻塞渲染。‘
1.使用transform替换top
2.使用visibility替换display:none,因为前者只会引发重绘,而后者会引发回流
3.少用table布局,因为table布局很小的一个改动会引发整个table的重新布局
4.将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点。(比如video标签,浏览器会自动将该节点变为图层)
XSS(Cross-Site Scripting)—跨站脚本攻击,简称XSS,是一种代码注入攻击,攻击者通过在目标网址注入恶意脚本,使之在用户的的浏览器上运行。利用这些恶意脚本,攻击者获取用户敏感信息如Cookie、SessionID等,进而危害数据安全
XSS的本质:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行
由于问题的源头是js代码的注入,那么我们便想办法不让js生效
方式1:使用转义字符
即需要注意两头的防范:
1)输入
在提交表单时,前端最好将文本内容转成html实体编码,也就是过滤掉<script>、<a>这样的标签,然后再提交到后台去
2)输出
在显示文本时,最好也要做一次html实体编码转换后再显示,防止<script>生效
方式2:CSP建立白名单
建立白名单,即是明确告诉浏览器哪些外部资源可以加载和执行。(我们只需要配置规则,如何拦截是由浏览器自己实现的)
通常可以通过两种方式来开启CSP:
1)设置HTTP Header中的Content-Security-Policy
2)设置meta标签的方式
CSRF中文名为跨站请求伪造,原理是攻击者诱导受害者进入第三方网站,在第三方网站中向被攻击网站发送跨站请求,利用受害者在被攻击已获取的注册凭证,绕过后台的验证,达到冒充用户对被攻击的网站执行某项操作的目的。
几种常见的攻击类型
1)GET类型的CSRF利用非常简单,只需要一个HTTP请求,一般会这样利用
<img src="http://bank.example/withdraw?amount=10000&for=hacker" >
在受害者访问这个img页面之后,浏览器会自动向http://bank.example/withdraw?amount=10000&for=hacker
发送一次http请求,bank.example就会收到包含受害者登录信息的一次跨域请求(因此此时受害访问了A网站,那么其是包含着认证信息的,攻击者利用这一特性,隐形中让受害者向上网站(B)发起HTTP请求,那么此时请求头自然也会包含了受害者的认证信息,那么攻击者的目的便达到!)
CSRF通常是第三方网站发起的,被攻击者的网站无法防止攻击的发生,只能通过增强自己的网站针对CSRF的防护能力来提升安全性
SCRF的两个特点:
针对以上两个特点,我们可以专门指定防护策略,如下:
阻止不明外域的访问
提交时要附加本域才能获取信息
点击劫持就是攻击者利用iframe将受害者网站嵌入自己的网页中,并将iframe设置为透明,在页面中透出一个按钮诱导用户点击。
通常可以使用以下两种方式进行防御:
1)设置HTTP响应头:X-FRAME-OPTIONS
这个响应头主要是用来防御iframe嵌套的点击劫持,其有三个可选值,分别是:
2)通过JS防御
因为有些浏览器不支持1)的方式
JS防御的原理是通过iframe的方式加载页面时,攻击者的页面直接不显示内容。
1.优化Loader
2.实现按需加载
比如在一个SPA项目中,项目会有十几个甚至更更多的路由页面,我们可以实现按需加载,以减少一些不必要代码的加载
1)Hash模式
Hash模式是根据#后面哈希值的变化时,触发了hashchange事件来监听到url的变化,从而进行页面的跳转。并且无论哈希值怎么样变化,服务器接收到的url永远都是#前面部分的url
如www.test.com/#/---------->www.test.com
2)History模式
History模式是H5新推出来的功能,主要使用history.pushState和history.repalceState改变url,同样,通过History模式改变url也不会引起页面的刷新,只会更新浏览器的历史记录
3)两种方式的区别
我当时使用webpack的主要原因是为了简化页面依赖的管理,并且通过将其打包为一个文件来降低页面加载时请求的资源数。
我认为webpack的主要原理是,它将所有的资源看成一个模块,并且把页面逻辑当成一个整体,通过一个给定的入口文件,webpack从这个文件开始,找到所有的依赖文件,将这个依赖文件模板通过loader和plugins处理后,然后打包在一起,最后输出一个浏览器可以识别的js文件。
简单的说,函数式编程是一种编程范式,也就是如何编写程序的方法论
它具有以下特性:闭包和高阶函数、惰性计算、递归
第一种最常见的就是回调函数的方式,使用回调函数的方式有一个缺点就是,多个回调嵌套的时候会造成回调函数地狱,上下两层的回调函数间的代码耦合度太高,不利于代码的可维护。
第二种是Promise的方式,使用Promise的方式可以将嵌套的回调函数作为链式调用,但是使用这种方法,有时会造成多个then的链式调用,可能会造成代码的语义不够明确。
第三种是使用async函数的形式,它内部自带执行器,当函数内部执行一个awiait语句的时候,如果语句返回一个promise对象,那么函数就会将等待promise对象的状态变为resolve后再继续向下执行。因此我们可以将异步逻辑,转换成同步的顺序来书写,并且这个函数可以自动执行。
URI:统一资源标识符
URL:统一资源定位符
URN:统一资源名称
PS:‘
1)URI指的是统一标识符,用唯一的标识来确定一个资源,它是一种抽象的定义,也就是说,不管使用什么方法来定义,只要能唯一标识一个资源,就可以成为URI
2)URL和URN是URI的子集,URL可以理解为使用地址来标识资源,URN可以理解为使用名称来标识资源。
缓存一般适用于那些不会更新服务端数据的请求,一般get请求都是查找请求,不会对服务器资源造成修改,而post请求一般都会对服务器数据造成修改,所以,一般会对get请求进行缓存,很少会对post请求进行缓存。
相关知识点:
懒加载:懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数
预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染
懒加载:
懒加载也叫做延迟加载,即是当用需要访问时,在去加载,这样可以提高网站首屏加载速度,提升用户的体验,并且还可以减少服务器的压力。它适用于图片很多时,页面很长的电商网站的场景。懒加载的实现原理是,将页面上的图片的src属性设置为空字符串,将图片的真是路径保存在一个自定义的属性中,当页面滚动时候,进行判断,如果图片进入页面可视区域,则从自定义的属性中取出真是路径赋值给图片的src属性,以此来实现图片的延迟加载。(比如在vue中使用v-lazy)
预先加载:
预先加载指得是将所需的资源提前加载到本地,这样后面在需要用到时就直接从缓存资源通过预加载能够减少用户的等待时间,提高用户的体验。我了解的预加载最常用的方式是使用js中的image对象,通过image对象设置src属性,来实现图片的预加载。
总:
这两种方式都是提高网页性能的方式,两者主0 要区别是一个要提前加载好,一个是延迟加载。懒加载对服务前端有一定的缓解压力的作用,预加载则会增加服务端压力。
设计模式可以分为三大类:
1. 结构型模式:通过识别系统中组件间的简单关系来简化系统色设计
2. 创建型模式:处理对象的创建,根据实际情况使用合适的方式创建对象
3. 行为型模式:用于识别对象之间常见的交互模式并加以实现,如此增加了这些交互的灵活性。
说明:你可以想象一个场景,假设有一份很复杂的代码需要用户去调用,但是用户并不关心这些复杂的代码,只需要你提供一个接口去调用,用户只负责传递需要的参数,至于这个参数怎么使用,内部逻辑不用关心,只需要你最后返回一个实例,这个构造过程就是工厂。
工厂起到的作用就是隐藏了创建实例的复杂度,只需要一个接口,简单清晰。
现实生活中的工厂按照既定的程序制造产品,随着生产原料和流程不同生产出来的产品也会有区别。应用到软件工厂的领域,工厂可以看成是一个制造其他对象的对象,制造出来的对象也会随着传入共产对象的参数的不同而有所区别
那么,什么时候适合使用共产模式而不是直接new一个对象呢?当构造函数过多不便管理,且需要创建的对象之间存在某些关联(有同一个父类,实现同一个接口)时,不妨使用工厂模式,工厂模式提供一种集中化,统一化的方式,避免了分散创建对象导致的代码重复、灵活性差的问题。
举例如下:(构造一个简单的汽车工厂来生产汽车)
//汽车构造函数
function Car1(color) {
this.color = color
this.brand = 'Car1'
}
//汽车构造函数
function Car2(color) {
this.color = color;
this.brand = 'Car2'
}
//汽车构造函数
function Car3(color) {
this.color = color;
this.brand = 'Car3'
}
//汽车的品牌
const BRANDS = {
car1: 1,
car2: 2,
car3: 3
}
//汽车工厂
function createCar() {
this.create = function (brand, color) {
switch (brand) {
case BRANDS.car1:
return new Car1(color);
case BRANDS.car2:
return new Car2(color);
case BRANDS.car3:
return new Car3(color);
default:
break;
}
}
}
//测试
const carFactory = new createCar();
const cars = [];
cars.push(carFactory.create(BRANDS.car1, 'red'))
cars.push(carFactory.create(BRANDS.car2, 'greed'))
cars.push(carFactory.create(BRANDS.car3, 'pink'))
function say() {
console.log(`Hi , I am ${this.color} and ${this.brand} car`)
}
for (const car of cars) {
say.call(car)
}
结果如下
使用工厂模式后,不再需要重复引入一个个构造函数,只需要引入工厂对象便可以创建各类对象
单例模式的核心就是保证全局只有一个对象可以访问,Class的实例个数最多为1,一般全局缓存、全局状态管理等待这些只需要一个对象,就可以使用单例模式。 即我们只需要用一个变量确保实例只创建一次就可以,以下为其实例:
class Singleton {
constructor() {
}
}
Singleton.getInstance = (function () {
let instance;
return function () {
//这里使用的闭包,使用闭包保存局部作用域中的单例对象并返回
if (!instance) {
instance = new Singleton();
}
return instance;
}
})()
let s1 = new Singleton.getInstance();
let s2 = new Singleton.getInstance();
console.log(s1 === s2) //true
设计思路:即当instance为空时,则new创建新对象,若不为空时返回原来的instance对象,因此使得每次都是同一个对象
代理是为了控制对对象的访问,不让外部直接访问到对象,也有很多代理的场景。比如事件代理就用到了代理模式。
<ul id="ul">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
let ul = document.querySelector('#ul');
ul.addEventListener('click', function (event) {
console.log(event.target)
})
</script>
因为存在太多的li,不可能内个都去绑定事件,这时可以通过给父节点绑定一个事件,让父节点作为代理去拿到真实点击的节点。
发布-订阅者模式也叫作观察者模式。通过一对一或者一对多的依赖关系,当对象发生改变时,订阅方也会收到通知。
let ul = document.querySelector('#ul');
ul.addEventListener('click', function (event) {
console.log(event.target)
})
function addEvent(ele, ebType, fn, useCapture) {
if (ele.addEventListener) {
ele.addEventListener(evType, fn, useCapture);
return true
} else if (ele.attachEvent) {
var r = ele.attachEvent("on" + evType, fn)
return r;
} else {
//均支持这种事件绑定方式
ele["on" + evType] = fn
}
}
对于不同浏览器,添加的事件的方式可能会存在兼容问题。如果诶次都需要去这样写一遍的话肯定是不能接受的,所以我们将这些判断逻辑统一封装在一个接口中,外部需要添加时间时只需要调用addEvent即可。
http:超文本传输协议,是互联网应用最广泛的一种网络协议,是一个客户端和服务器请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,可以使浏览器更加高效,使网络传输减少。
https:是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP加上了SSL层,HTTP的安全基础是SSL,因此加密的详细内容即是需要SSL
https协议的主要作用是:建立一个信息安全通道,来确保数组的传输,确保网站的真实性。
http传输的数据都是未加密的,也就是明文的。网景公司设置了SSL对http进行了加密,简单来说,https就是构建在http与SSL的基础上可进行加密传输和身份认证的网络协议,比http协议的安全性高。
客户端需要使用https url访问服务器,则需要与web服务器建立ssl连接,web服务器接收到客户端的连接请求之后,会将网络的证书(证书中包含了公钥),返回或者说传输给客户端。
客户端和web服务端则会协商ssl链接的安全等级
客户端浏览器通过双方协商一致的安全等级,建立会话秘钥,然后通过网站的公钥来加密会话秘钥,并传送给网站
web服务器端通过自己的私钥来解密出会话秘钥
web服务端通过会话秘钥来加密与客户端之间的通信
(1)TCP是面向连接的,而UDP是面向无连接的即数据发送之前不需要建立连接
(2)TCP提供可靠的服务,也就是说通过TCP连接传送的数据,无差错、不丢失,不重复。而UDP是只管尽最大的努力交付数据,即不保证数据可靠数据。
(3)TCP只能一对一,UDP支持一对一、一对多
(4)TCP收不较大为20字节,而UDP只有8字节
(5)TCP是面向连接的可靠性传输,而UDP是不可靠的
head:类似于get请求,只不过返回的响应中没有具体的内容,用户获取报头
options:允许客户端查看服务器的性能
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!