Vh虽然获取到了视口高度,但是vh会随着屏幕的、大小变化,所以当减去一个数字之后,就会显示错误。
生成id
如果没有设置id,则可以通过new Date.getTime()获取一个时间,作为一个单独的id,也可以通过下载uuid生成新的id。
word-wrap: break-word
使用CSS属性word-wrap: break-word。这个属性可以让超出宽度的文本自动换行,并在合适的位置将单词断开。
重排和重绘
重排:重新排布,渲染树的一部分必须更新,并且节点尺寸发生了变化,浏览器则需要重新构造渲染树。
如:页面初始化
添加或删除可见的dom元素
元素的位置、尺寸改变,使用动画(引起位置的变化)
内容改变
浏览器的窗口尺寸改变(resize 事件是在浏览器窗口大小发生变化时触发,利用该事件可以跟踪窗口大小的变化来动态调整页面的元素显示。)
设置style属性的值
计算offsetWidth、offsetHeight、offsetTop和offsetLeft等布局信息
激活CSS伪类(如 :hover)
查询某些属性或调用某些方法(如:getComputedStyle()、getBoundingClientRect())
重绘:一个元素的外观被改变,浏览器根据新属性重新绘制,使元素呈现新的外观。
外观属性包括界面、文字等可用状态向量描述的属性,如:
界面:appearance、outline、background、mask、box-shadow、box-reflect、filter、opacity、clip、border-radius、background-size、visibility
文字:text、font、word
call,apply和bind的作用和区别?
相同点:
1:都能改变this指向
2:都能传递参数
3:都能通过方法"."方法名调用
不同点:
1:函数名不同
参数传递方式不同(注意看第二个)
改变this指向的时机不同(bind在复制时改变,其他两个在调用时改变)
参数传递时机不同(注意看第三个)
宏任务和微任务:
宏任务:从浏览器事件中取出事件,交给javascript引擎执行、异步队列取出毁掉函数执行。I/O事件队列中取出事件执行。一般是延时函数,如setTimeout,setInterval,setImmdeiate
微任务:微任务产生后推到执行队列中,等执行完宏任务后,优先执行队列中的微任务,直到微任务队列为空,再去执行下一个宏任务。一般是Promise产生的
数组去重:
function unique(arr){var result = [];for(var i=0; i<arr.length; i++){if(result.indexOf(arr[i]) === -1){result.push(arr[i]);}}return result;}const arr = [1,1,2,3,4,4]
const x = unique(arr)
console.log(x); //[1,2,3,4]
数组扁平化:
(将一个多维数组变成一个一维数组,主要由flatten函数实现,意思是摊平)
方法1:
function flatten(arr) {let result = [];// 此处也可使用for...of遍历for (let i = 0; i < arr.length; i++) {if (Array.isArray(arr[i])) {result = result.concat(flatten(arr[i]));} else {result.push(arr[i]);}}return result;}
方法2:
function flatten(arr) {return arr.toString().split(',').map((item) => Number(item));},
方法3:
方法4:
直接使用ES6提供的flat方法实现扁平化。falt()方法会按照指定的深度递归遍历数组,arr.flat([depth]),参数depth不填时默认值为1,depth为Infinity表示展开任意深度的嵌套数组。
function flatten(arr) {return arr.flat(Infinity);}
柯里化:
一个接受多个参数的函数。它将把这个函数转换成一系列函数,其中每个小函数将接受一个参数,直到所有参数都完成。
// 非柯里化
const add = (a, b, c) => {return a + b + c}
console.log(add(2, 3, 5)) // 10
// 柯里化
const addCurry = (a) => {return (b) => {return (c) => {return a + b + c}
}}
console.log(addCurry(2)(3)(5)) // 10
偏函数:
当给定的参数少于预期的参数时,函数将转化为偏函数,并返回一个期望剩余参数的新函数。
const addPartial = (x, y, z) => {return x + y + z}
const partialFunc = addPartial.bind(this, 2, 3)partialFunc(5) // 10
IndexOf()查找字符串中某一字符从头开始第一次出现的索引
B标签:加粗标签 I标签:斜体 U标签:下划线
深拷贝与浅拷贝的区别:
假设源对象是A,拷贝后的对象是B。
总的来说,浅拷贝后的A和B两个对象指向同一个地址,深拷贝后两者指向不同的地址。
具体来说,浅拷贝后,修改B对象内的值后,A对象内对应的值也会改变;而深拷贝则不会。
浅拷贝只克隆了最外一层,而深拷贝需要递归拷贝每一层。这只是对于数组、json等对象来说存在区别;对于基本数据类型来说,两者意义相同。
类数组转换成数组
类数组定义
var alo = {0: "a", 1: "b", 2: "c", length: 3};
类数组是一个对象,拥有length属性,其他属性为非负数
例如arguments和DOM方法的返回结果,都是类数组
转换方法
var arr = Array.prototype.slice.call(alo);// es5方法Array.isArray(alo); // falseArray.isArray(arr); // truevar arr1 = Array.from(alo); // es6方法// 关于扩展运算符 ...// ... 只适用于具有遍历器接口 Symbol.iterator 的对象// 如果一个对象没有部署这个接口,就无法转换
SEO
SEO是指通过了解搜索引擎的规则和算法,对网站进行内部和外部的优化,提高网站在搜索引擎自然排名中的位置,从而增加网站的曝光度和流量。SEO的目的是为了提高网站的可见性,吸引更多的访问者,并将这些访问者转化为潜在客户或购买者。具体来说,SEO包括网站结构优化、页面优化、内容质量优化和外部链接优化等方面。同时,通过监测和分析网站收录情况、排名情况、外部链接数据和流量数据等指标,可以量化地检测SEO的效果。
em和rem
em是相对于父级的字体大小,rem是相对于根元素的字体大小。
什么叫优雅降级和渐进增强?
渐进增强 progressive enhancement:
针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。
优雅降级 graceful degradation:
一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。
区别:
a. 优雅降级是从复杂的现状开始,并试图减少用户体验的供给
b. 渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要
c. 降级(功能衰减)意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处于安全地带
浏览器的内核分别是什么?
IE: trident内核
Firefox:gecko内核
Safari:webkit内核
Opera:以前是presto内核,Opera现已改用Google Chrome的Blink内核
Chrome:Blink(基于webkit,Google与Opera Software共同开发)
强缓存和弱缓存(协商缓存)
优点:减少不必要的数据传输、减轻对服务器的压力、加快网页加载速度
缺点:可能会出现缓存失效
无法保证缓存数据与数据库中的数据保持同步。
强缓存
强缓存其实就是强制缓存的意思。当浏览器去请求某个文件的时候,服务端就在respone header里面对该文件做了缓存配置。缓存的时间、缓存类型都由服务端控制,具体表现为:
respone header 的cache-control,常见的设置是max-age public private no-cache no-store等1.cache-control: max-age=xxxx,publicmax-age:表示缓存的时间(有效期)public:表示客户端和代理服务器都可以缓存该资源;但是,当用户重新刷新页面时,就会重新 发送请求,获取资源2.cache-control: max-age=xxxx,privateprivate:表示只让客户端可以缓存该资源;代理服务器不缓存3.cache-control: max-age=xxxx,immutableimmutable:表示即使用户重新刷新页面,也不会重新发送请求,还是直接读取缓存4.cache-control: no-cacheno-cache:表示不走强制缓存,但可以走协商缓存5.cache-control: no-storeno-store:表示不走缓存
协商缓存
当强制缓存时间过期后,这是客户端就会去请求服务器,在请求服务器的过程中可以设置协商缓存。
协商缓存主要由 ETag 和 Last-Modified 两个字段来实现
ETag 是一个用于映射 web 资源的映射 token,具有唯一性
Last-Modified 则通常是文件最后更新的日期时间戳
总结
强制缓存发生在浏览器端, 协商缓存发生在服务器端
强制缓存在浏览器强制刷新的情况下不会生效, 而协商缓存则不受影响。
强制缓存返回的报文状态码为 200, 协商缓存返回的报文状态码为 304
样式合集
font-family:ajax(设置英文字体可以不带双引号)background-position:背景图像位置;注意:背景图像你想让它在页面的哪个位置显示,它就可以在哪个位置显示,但前提是你要使用这个属性,通常同时设置 x 轴(横轴)和 y 轴(纵轴)。例如: background-position:300px 400px;。z-index:控制网页的叠放顺序,为元素设置重叠效果。属性使用纯整数,为0时位于最下方,适用于绝对定位或者相对定位。white-space:控制空格的输入,有normal、pre(保留空格)和不换行(nowrap)
布局:
常规布局:
块级默认为:display:block;
行级元素:display: inline;
弹性盒子布局:
display: flex;
flex-direction:默认是row(横向排放)
column(纵向排放)
row-reverse——你会看到仍然有多行布局,但是每一行元素排列的方向和原来是相反的了。
flex-wrap: wrap 换行显示
flex:200 为页面中的每个内容至少设置为200px宽
网格布局:
display: grid;grid-template-columns: 1fr 1fr 1fr;创建三个1fr的列。这里的数字代表显示的比例,可根据情况更改。grid-column-gap:定义列之间的间隙。grid-row-gap:定义行之间的间隙。grid-gap: 同时定义行和列之间的间隙。(这里的grid- 可以省略,只写gap也可以)grid-auto-rows: minmax(100px, auto);minmax(100px,auto),定义了一个行/列尺寸至少为100px,并且尺寸大于100px就会进行自动调整。position: absolute;绝对定位的元素不再存在于正常文档布局流中。它坐在它自己的层独立于一切。默认情况下 position 属性都是 static。
多列布局:
.container {column-count: 3;//会将页面等分成三列column-width: 200px;//设置列宽column-gap: 20px;//改变列之间的间隙column-rule: 4px dotted rgb(79, 185, 227);//在列之间加入一条分割线
}
链接状态:
样式合集2:
outline属性在声明中设置多个轮廓属性的简写属性,例如:outline-style, outline-width和outline-color, outline: green solid 3px;outline和border设置的值类似,但是不同的是,outline不占据空间,绘制于元素内容周围。outline-offset 里面元素边框和外面设置的outline之间的间隙overflow:visible/hidden/clip(类似于hidden)/scroll/auto/overlay(这三个都能把隐藏的内容以滚动的形式呈现出来。overflow-x,overflow-y和overflow的属性值一样,分别控制了内容是横向滚动还是纵向滚动。overflow-wrap 应用于行级元素,用来设置浏览器是否应该在一个本来不能断开的字符串中插入换行符,以防止文本溢出其行向盒。属性值,normal(单个字符串过长会横向溢出)anywhere(会造成下方溢出)break-word(这个不造成溢出,会正确的显示)
缓存种类:
1.私有缓存:
通常是浏览器缓存,不与其他客户端共享,因此私有缓存存储在该用户的个性化响应中。个性化的内容由cookie控制,但是单独的cookie不会响应成为私有的。
请注意,如果响应具有 Authorization 标头,则不能将其存储在私有缓存(或共享缓存,除非 Cache-Control 指定的是 public)中。
只想将响应存储在私有缓存中,则Cache-Control: private
2.共享缓存:
位于客户端和服务端之间,存储用户之间的响应,分为代理缓存和托管缓存。
(1)代理缓存:进行访问控制、实现缓存、减少网络流量。
(2)托管缓存:由服务开发人员部署,降低源服务器负载。
Http的重定向:
重定向操作由服务器向请求发送特殊的重定向响应而触发。对于用户来说重定向的影响几乎是不可见的。
永久重定向:表示原 URL 不应再被使用,而选用新的 URL 替换它。
临时重定向:有时候请求的资源无法从其标准地址访问,可以从另外的地方访问。
特殊重定向:304(Not Modified)会使页面跳转到本地的缓存副本中(可能已过时)
而 300(Multiple Choice)则是一种手动重定向:将消息主体以 Web 页面形式呈现在浏览器中,列出了可能的重定向链接,用户可以从中进行选择。
HTTP 重定向不是定义重定向的唯一方法。
1.借助 HTML 的 <meta> 元素的 HTML 重定向机制。在页面的 <head> 中添加一个 <meta> 元素。
2.借助 DOM 的 JavaScript 重定向机制。原理是设置 window.location 的属性值,然后加载新的页面。
window.location = "https://example.com/";
只有在执行 JavaScript 的客户端上才能使用。
优先级:HTTP协议>HTML重定向>javascript重定向机制。
HTTP1.0和HTTP1.1和HTTP2.0的区别:https://www.jianshu.com/p/be29d679cbff
影响一个 HTTP 网络请求的因素主要有两个:
带宽(之前是拨号上网,现在基本上不会影响)和延迟。
延迟:浏览器阻塞、
DNS查询(浏览器需要知道目标服务器的 IP 才能建立连接。将域名解析为 IP 的这个系统就是 DNS。这个通常可以利用DNS缓存结果来达到减少这个时间的目的。)、
建立连接:HTTP 是基于 TCP 协议的,浏览器最快也要在第三次握手时才能捎带 HTTP 请求报文,达到真正的建立连接,但是这些连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。
HTTPS与HTTP的一些区别:
1.https需要付费
2.http协议运行在TCP上,传输的内容是明文,Https运行在SSL/TLS之上,SSL/TLS运行在TCP上,所有的传输内容则是经过加密的
3.传输方式不同/端口不同:http协议明文传输,端口是80、Https加密传输,端口是443。
4.HTTPS有效防止运营商劫持
服务端推送是什么:
把客户端需要的资源随着index.html一起发送到客户端,省去客户端重复请求的步骤,加快静态资源通过服务端推送的方式的速度。
HTTP2.0多路复用的好处:
HTTP 性能优化的关键并不在于高带宽,而是低延迟。TCP 连接会随着时间进行自我调谐,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度。这种调谐则被称为 TCP 慢启动。由于这种原因,让原本就具有突发性和短时性的 HTTP 连接变的十分低效。
HTTP/2 通过让所有数据流共用同一个连接,可以更有效地使用 TCP 连接,让高带宽也能真正的服务于 HTTP 的性能提升。
SPDY:
优化HTTP1.X的请求延迟,解决HTTP1.X的安全性,具体如下:
1.降低延迟:采用多路复用,多个请求stream共享一个tcp连接的方式,降低延迟,提高了带宽利用率。
2.请求优先级:多路复用带来新问题,关键请求可能被阻塞。给每个request设置优先级,这样重要的请求被优先响应(如浏览器首页),之后加载各种静态资源、脚本文件,保证用户第一时间看到网页的内容。
3.header压缩:很多都是重复多余的,选择合适的压缩算法减少包的大小和数量。
4.增加基于HTTPS的加密传输协议
5.由服务端推送,就是当请求一个style.css,服务器传输style.css同时传输了style.js,当再请求style.js的时候,就会直接在缓存中获取到,不用再多发一次请求。
HTTP2.0 与 SPDY 的不同点:
不同于SPDY的是,HTTP2.0支持明文HTTP的传输,而SPDY强制使用HTTPS。
消息头的压缩算法不同。
HTTP2.0与HTTP1.x相比之下的新特性:
HTTP2.0的解析是基于二进制的,HTTP1.x是基于文本的。
多路复用(连接共享),一个request对应一个id。request可混杂,通过id归属不同的分类。
header压缩:HTTP1.x的header有大量信息,每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
服务端推送。
HTTP2.0的多路复用和HTTP1.X中的长连接复用的区别:
网络模型自上而下分为 应用层、传输层、网络层和网络接口层。
上面的元素设置了 margin-bottom,下面的元素设置了 margin-top,这种情况下,会按照较大者去显示。
CSS变量:
在样式中,以—开头的都是CSS变量,之后通过var进行使用。变量值不能有单位,不能是‘20px’这样
/*** var()函数就是用于读取变量* color: var(—黑色, #fff); //第二个参数就是默认值,* 假设—黑色为空情况下,会使用#fff**/body {color: var(--1)—黑色: #000000 //这里是变量background-color: var(--黑色, #fff)}
Vue 中 computed 和 watch 区别:
Computed:
1.支持缓存,只有依赖的数据发生变化后才会重新计算,不支持监听异步操作。
2.其值默认走缓存,计算属性是基于他们的响应式依赖进行缓存的,即data声明过/父组件通过props传递的。
3.如果一个属性是由其他属性计算而来的,这个属性依赖其他的属性,一般会使用computed
4.在computed中,属性有一个get方法和一个set方法,当数据发生变化时,会调用set方法。
Watch:
1.不支持缓存,数据变化则触发操作
2.支持监听异步操作
3.监听的函数接收两个参数,一个最新值,一个变化前的
4.当一个属性变化,就需要执行相应的操作
5.监听数据必须是data中声明的或者父组件传递过来的props中的数据, 当发生变化时,会触发其他操作,函数有两个的参数:
immediate: 组件加载立即触发回调函数
deep: 深度监听,发现数据内部的变化,在复杂数据类型中使用,例如数组中的对象发生变化。需要注意的是,deep无法监听到数组和对象内部的变化。
当想要执行异步或者昂贵的操作以响应不断的数据变化的时候,则就需要watch。
严格模式中,函数独立调用 this 默认绑定 undefined,而在草率模式中则绑定 globalThis。
一旦代码中使用了 class 关键字,类区块中的所有语法将在严格模式下执行。类作用域默认能且仅能支持严格模式。
严格模式下禁止使用with语句,但是Vue的编译器依赖with语句实现。序列化:就是不直接使用 with 语句,而是间接使用,比如把 with 语句变成字符串,然后交给 eval/Function 执行,但是这里的eval必须是间接调用,直接调用的话还是会被全局下的严格模式捕获。
判断全局是否开启了严格模式:函数独立调用时,在严格模式下 this 绑定 undefined,在草率模式下则绑定 globalThis。
无法判断局部开启了严格模式。
filter 过滤的内容是浅拷贝过程
内部机制:
所谓内部机制,指的就是:
1判断x是否有valueOf方法,如果有的话根据其返回值做出不同的反映:
返回值为symbol类型,报错
返回值为引用类型, 跳到2
返回值y为其它非引用类型,最终结果为:String(y)
2如果没有valueOf方法,或valueOf返回引用类型,则接着判断是否有toString方法,如果有的话根据其返回值做出不同的反映:
返回值为symbol类型,报错
返回值为引用类型,报错
返回值y为其它非引用类型的y,最终结果为:String(y)
3 如果没有toString方法,则返回Object.prototype.toString,call(x)
假值
也就是不能通过if()判断的值:
""
false
+0
-0
NaN
null
undefined
Boolean(false)
这些易混淆的,是真值,可以通过if()判断
![]
!({})
!123n
!Symbol(0)
!Object(false)
&& || ??
|| 和 ??的作用相同,都是代表“或”的意思。??只对undefined和null生效,当输出
(0 ?? 20)时,执行结果为0,不是20。
isNaN和Number.isNaN的区别
isNaN()的作用是检查其参数是否是非数字值,如果是则返回true,反之,false。
Number.isNaN()的作用是判断传递的值是否为 NaN,并且检查其类型是否为 Number。
如果值为 NaN 且类型为 Number,则返回 true,否则返回 false。
Object.is(a,b)的判断机制是:
检查是否符合两种特例,如果不符合,则直接返回a===b的结果
特例一:a和b都是NaN,此时应该返回true
特例二:a和b都是0,只不过一个为正一个为负,此时需要返回false
手写Object.is:
ps: 1 / Infinity === 0;的结果是true.
function myObjectIs (a, b) {
if(Number.isNaN(a) && Number.isNaN(b)) return true;
if(a===0 && b===0 && 1/a!==1/b) return false;
return a===b;
}
(123).toString(16) //输出’7b'
type和interface的区别:
对象扩展的情况下,使用接口继承比交叉类型的性能更好。
interface可以重复申明,Type不可以重复申明
继承方式不一样:interface使用extends实现,
Type使用交叉类型方式。
1px
有些设备显示的1px会有点粗,并没有显示真正1px的效果。是因为不同的设备之间有一个比例关系。
window.devicePixelRatio = 设备的物理像素 / CSS像素
像在浏览器里面输出为2,在移动端则输出是3。
输出的结果是几,就证明该设备是用几个物理像素单元来进行渲染的。
解决方案就是按比例缩小值。例如:
#container[data-device="2"] {
border:0.5px solid #333
}
CDN:
内容分发网络:同过互联网互相连接的电脑网络系统,利用最近的服务器,进行传递文件等。组成部分:
分发服务系统: 最基本的工作单元就是Cache设备,cache(边缘cache)负责直接响应最终用户的访问请求,把缓存在本地的内容快速地提供给用户。同时cache还负责与源站点进行内容同步,把更新的内容以及本地没有的内容从源站点获取并保存在本地。Cache设备的数量、规模、总服务能力是衡量一个CDN系统服务能力的最基本的指标。
负载均衡系统: 主要功能是负责对所有发起服务请求的用户进行访问调度,确定提供给用户的最终实际访问地址。两级调度体系分为全局负载均衡(GSLB)和本地负载均衡(SLB)。全局负载均衡主要根据用户就近性原则,通过对每个服务节点进行“最优”判断,确定向用户提供服务的cache的物理位置。本地负载均衡主要负责节点内部的设备负载均衡
运营管理系统: 运营管理系统分为运营管理和网络管理子系统,负责处理业务层面的与外界系统交互所必须的收集、整理、交付工作,包含客户管理、产品管理、计费管理、统计分析等功能。
提高webpack打包速度的方法:
(1)优化loader,因为Babel将代码转为字符串生成AST,AST生成新代码,项目越大,转换的代码越多,效率越低。
方法:
1.缩小优化范围,只优化src文件夹下的内容。
module.exports = {
module: {
rules: [
{
// js 文件才使用 babel
test: /\.js$/,
loader: 'babel-loader',
// 只在 src 文件夹下查找
include: [resolve('src')],
// 不会去查找的路径
exclude: /node_modules/
}
]
}
}
2.缓存已编译的内容,下次只需要编译新的代码文件即可。
loader: 'babel-loader?cacheDirectory=true'
(2)webpack打包是单线程的,HappyPAck可以把loader的同步改成并行的。
module: {
loaders: [
{
test: /\.js$/,
include: [resolve('src')],
exclude: /node_modules/,
// id 后面的内容对应下面
loader: 'happypack/loader?id=happybabel'
}
]
},
plugins: [
new HappyPack({
id: 'happybabel',
loaders: ['babel-loader?cacheDirectory'],
// 开启 4 个线程
threads: 4
})
]
(3)DllPlugin:将特定的类库提前打包然后引入,减少打包类库的次数,更新版本才重新打包。
(4)代码压缩:webpack3中使用UglifyJS,但这个是单线程的,使用webpack-parallel-uglify-plugin 来并行运行 UglifyJS,从而提高效率。
webpack4中直接将mode设置为production默认开启上面的功能。
Promise有三种状态:
pending(待处理),fulfilled(成功),rejected(失败)。
当Promise对象被创建时,初始状态为pending。成功完成异步操作后,状态变为fulfilled。异步操作失败时,状态变为rejected。
预防XSS攻击:
1.使用CSP:
CSP 指的是内容安全策略,它的本质是建立一个白名单,告诉浏览器哪些外部资源可以加载和执行。我们只需要配置规则,如何拦截由浏览器自己来实现。
通常有两种方式来开启 CSP,一种是设置 HTTP 首部中的 Content-Security-Policy,一种是设置 meta 标签的方式
2.不使用服务端渲染/对需要插入到 HTML 中的代码做好充分的转义
3.对敏感信息进行保护,比如cookie使用http-only,让脚本无法获取。或者使用验证码,避免让脚本伪装成用户执行操作。
CSRF攻击:
“跨站请求伪造”攻击,引诱用户点击第三方网站,然后该网站向被攻击网站发送跨站请求。如果用户在被攻击网站中保存了登录状态,那么攻击者就可以利用这个登录状态,绕过后台的用户验证,冒充用户向服务器执行一些操作。本质是利用cookie会在同源请求中携带发送给服务器的特点,冒充用户。
类型:
GET 类型的 CSRF 攻击,比如在网站中的一个 img 标签里构建一个请求,当用户打开这个网站的时候就会自动发起提交。
POST 类型的 CSRF 攻击,比如构建一个表单,然后隐藏它,当用户进入页面时,自动提交这个表单。
链接类型的 CSRF 攻击,比如在 a 标签的 href 属性里构建一个请求,然后诱导用户去点击。
预防攻击:
使用Token验证:在每个表单中添加一个独特的Token,并将其与用户的会话相关联。当用户提交表单时,服务器会验证Token的有效性,以确保请求是合法的。
检查Referer头:服务器可以检查请求的Referer头,确保请求来自与当前网站相同的源。然而,这种方法并不可靠,因为Referer头可以被篡改或禁用。
使用双重Cookie验证:除了常规的会话Cookie之外,服务器还可以在用户浏览器中设置一个额外的Cookie,并将其值与会话相关联。当用户提交请求时,服务器会验证这两个Cookie的值是否匹配,以确保请求是合法的。
启用CSRF保护框架:使用专门的CSRF保护框架(如OWASP CSRFGuard或 Django CSRF Middleware)可以自动处理CSRF攻击的防御,减轻开发人员的负担。
防抖和节流:
防抖就是多次触发,只执行最后一次,节流就是规定时间内,只触发一次。
对项目中的图片进行优化:
1.对没必要的装饰作用的图片用CSS实现
2.移动端一般使用CDN加载,计算出适配屏幕的宽度,请求相应裁好的图片。
3.小图使用base64格式。
4.将图标文件整合到一张雪碧图中,通过CSS调整位置进行使用。
5.对于能够显示 WebP 格式的浏览器尽量使用 WebP 格式。因为 WebP 格式具有更好的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量,缺点就是兼容性并不好,有些国内的浏览器并不支持WebP格式的图片。
小图使用 PNG,其实对于大部分图标这类图片,完全可以使用 SVG 代替。
照片使用 JPEG。
三栏布局的实现:
左右两边宽度固定(使用绝对定位),中间部分自适应(中间设置margin-left/right的不同值,达到对应的要求,也可以设置flex:1,占据剩余空间)。
圣杯和双飞翼布局区别:
共同点在于都实现了三栏布局,并且中间部分内容写在前面,先渲染这部分内容。主要的不同之处就是在解决中间部分被挡住的问题时,采取的解决办法不一样。圣杯布局是在父元素上设置了padding-left和padding-right,再给左右两边的内容设置position为relative,通过左移和右移来使得左右两边的内容得以很好的展现,而双飞翼布局则是在中间这个div的外层又套了一个div来放置内容,在给这个中间的div设置margin-left和margin-right 。
H5新特性:
语义化标签: `header`、`footer`、`nav`、`section`、`article`、`aside` 等
增强型表单:`date`(从一个日期选择器选择一个日期) 、`email`(包含 e-mail 地址的输入域) 、`number`(数值的输入域) 、`range`(一定范围内数字值的输入域) 、`search`(用于搜索域) 、`tel`(定义输入电话号码字段) 等
视频和音频:`audio`、`video`
`Canvas`绘图、 `SVG`绘图
地理定位:`Geolocation`
拖放API:`drag`
`web worker`:是运行在后台的 `JavaScript`,独立于其他脚本,不会影响页面的性能
`web storage`: `localStorage`、`sessionStorage`
`WebSocket`: `HTML5` 开始提供的一种在单个 `TCP` 连接上进行全双工通讯的协议
SVG和CANVAS的区别:
1.svg是矢量图,canvas是像素图。
2.svg适用于静态图形,canvas适用于动态图形,创建大量图形对象和复杂动画。
3.svg的每个绘制元素都是一个独立的DOM元素,轻松和javascript交互。canvas中,所有绘制都放置在一个画布中,只能和像素级别交互。
style标签prefetch和preload区别?
<style>标签的`prefetch`和`preload`属性都用于优化CSS资源的加载,但它们有不同的行为和目的:
`prefetch`属性告诉浏览器这个CSS资源可能在未来的某个时刻需要被加载,但并不需要立即加载。浏览器会在空闲时间异步加载这个资源,以便在需要时能够立即使用。`prefetch`适用于那些当前不需要但是可能在未来会需要使用的资源。
`preload`属性则告诉浏览器这个CSS资源在当前页面中必须被使用,因此应该立即加载和执行。浏览器会在主HTML文档下载和解析完成之前加载这个资源。`preload`适用于那些当前需要使用的资源。
defer 和 async 都是用于脚本加载和执行的关键字,主要区别:
1. defer 脚本会在 HTML 文档解析完成后执行,而 async 脚本会在下载完毕后立即执行。
2. defer 脚本会按照它们在文档中的顺序执行,而 async 脚本是在下载完成后尽快执行,可能会打乱它们在文档中的顺序。
3. defer 脚本会在 DOMContentLoaded 事件之后运行,而 async 脚本则不一定。
因此,如果需要按顺序执行脚本并且不想阻塞 DOM 的解析,可以使用 defer。如果脚本的执行不依赖于其他脚本或 DOM,可以使用 async 加快加载速度。
link 和 @import的区别:
<link>是HTML标签
在页面载入时同时加载
可以在文档任何地方定义
可以同时加载多个外部样式表
支持添加一些额外属性,如`media`、`title`等
支持动态插入
@import是CSS提供的一种方式
页面载入完成后加载
只能在样式表里面定义
必须一条一条执行
不支持附加功能
不支持动态插入
块格式化上下文(Block Formatting Context)、工作原理以及形成条件?
块格式化上下文(Block Formatting Context,BFC)是一个独立的渲染区域,在这个区域内,元素的布局和外部元素互不影响。BFC是 Web 页面布局中的一种重要机制,主要用于控制块级元素的布局及其内部元素的排列方式。
BFC的工作原理:
1. 内部的块级盒子会在垂直方向一个接一个放置。
2. 块级盒子的垂直间距(margin)会发生折叠。相邻的块级盒子的上下外边距会取最大值,而非相加。
3. BFC的区域不会与浮动盒子重叠。在计算布局时,BFC会考虑浮动元素的占用空间,从而避免与浮动元素重叠。
4. 计算BFC的高度时,浮动元素也参与计算。
5. BFC是一个独立的容器,外部元素对其内部元素布局没有影响;同样,BFC内部元素的布局也不会影响外部元素。
形成BFC的条件:
要创建一个BFC,需要满足以下条件之一:
1. 根元素(`<html>`)。
2. 浮动元素(`float`属性为`left`或`right`)。
3. 绝对定位元素(`position`属性为`absolute`或`fixed`)。
4. 内联块(`display`属性为`inline-block`)。
5. 表格单元格(`display`属性为`table-cell`)。
6. 表格标题(`display`属性为`table-caption`)。
7. 匿名表格单元格(`display`属性为`table`、`table-row`、`table-row-group`、`table-header-group`、`table-footer-group`、`table-column`、`table-column-group`)。
8. 元素的`overflow`属性值不为`visible`(例如,`auto`、`scroll`、`hidden`)。
9. 弹性盒子(`display`属性为`flex`或`inline-flex`)。
10. 网格容器(`display`属性为`grid`或`inline-grid`)。
11. 多列容器(`column-count`或`column-width`属性不为`auto`)。
12. `contain`属性值为`layout`、`paint`或`strict`。
通过满足以上条件之一,可以创建BFC,实现独立渲染区域。在实际应用中,BFC有助于解决外边距折叠、浮动元素引起的布局问题等。
什么是变量提升?
变量提升就是变量和函数申明在内部的任何位置都会被提升到它们所在的作用域的顶部,但是,提升的作用仅仅在于声明,不会影响赋值和初始化,提升之后该变量被认为是“undefined”,只有运行到后面的赋值语句后,才能被赋准确的值。只有var可以被提升。函数声明也会被提升,并且优先级高于变量。如果一个函数和一个变量同名,且变量未被赋值,那么该名称指向函数。
mouseover/mouseout 与 mouseenter/mouseleave 的区别与联系
mouseover和mouseout是HTML DOM事件,它们会在鼠标移入或移出元素时触发。它们也会在鼠标指针进入或离开**子元素**时触发。这也就是说,如果在父元素上有mouseover事件,并且鼠标指针进入子元素,则该元素上仍然会触发mouseover事件。mouseout同理。
mouseenter和mouseleave事件也是在鼠标进入或离开元素时触发。与mouseover和mouseout不同的是,mouseenter和mouseleave事件**不会传播到子元素**。因此,如果鼠标指针进入或离开元素的子元素,则不会触发mouseenter和mouseleave事件。
event.stopPropagation()与event.stopImmediatePropagation的区别
event.stopPropagation()可以阻止事件冒泡到父元素,但不阻止其他事件处理程序的执行。而event.stopImmediatePropagation()可以立即阻止事件冒泡并取消同一元素上其他事件处理程序的执行。
事件循环机制(Event Loop):
1.javascript引擎执行全局同步代码(<script>)
2.遇到异步操作,先把它们的毁掉函数按照类别放到微任务队列或者宏任务队列中。
3.同步代码执行完后,先去转去执行微任务队列中的事件,直到微任务队列为空。
4.开始执行宏任务队列中的第一个宏任务,执行完后去检查微任务队列中是否有微任务,有的话全部执行,没有则转去执行宏任务队列中的任务,以此类推,直到完成两个队列中的所有任务。
5.事件循环等待新的任务。开启1-4的步骤。
事件循环的目标是在处理同步代码和异步回调之间保持平衡,确保 JavaScript 代码的执行效率和响应能力。通过这种方式,事件循环允许 JavaScript 在单线程环境中有效地处理并发操作。
javascript栈内存和堆内存:
1. 栈内存(Stack Memory):
- 栈内存主要用于存储基本类型(原始类型)的值,如 `number`、`string`、`boolean`、`null` 和 `undefined`。这些类型的值通常较小且固定大小。
- 栈内存还负责存储函数调用的执行上下文、局部变量和临时数据。
- 栈内存遵循后进先出(LIFO)的原则进行分配和释放空间。当函数被调用时,函数的执行上下文、局部变量和相关信息会被压入栈中;当函数返回时,这些数据会从栈中弹出。
- 栈内存的分配和回收速度较快,因为内存管理由 JavaScript 引擎自动完成。
- 由于栈内存有限,如果递归调用过深或者分配大量的局部变量,可能导致栈溢出。
2. 堆内存(Heap Memory):
- 堆内存主要用于存储引用类型的值,如对象(`object`)、数组(`array`)和函数(`function`)。这些类型的值通常较大,大小不固定。
- JavaScript 引擎使用垃圾回收机制自动管理堆内存中的对象。当对象不再被引用时,它们会被标记为垃圾,并在下一次垃圾回收时释放内存。
- 与栈内存相比,堆内存分配和回收速度较慢,因为需要管理更复杂的数据结构和垃圾回收机制。
- 堆内存可以动态分配,因此可以存储更多数据。
- 如果没有正确处理引用关系,可能导致内存泄漏。
总结一下,在 JavaScript 中,栈内存用于存储基本类型的值、函数调用的执行上下文和局部变量,堆内存用于存储引用类型的值。
箭头函数的this是根据声明的位置确定的,而不是调用的位置,因此是申明时决定的,这个特性被称为“词法/静态作用域”。
严格模式(strict mode)和非严格模式(sloppy mode)的主要区别:
1. 变量声明: 在严格模式下,必须明确地声明变量(使用`let`、`const`或`var`关键字)。否则,将会抛出一个引用错误(ReferenceError)。在非严格模式下,如果没有声明变量,JavaScript会自动将其声明为全局变量,这可能会导致意外的全局污染。
2. this指针: 在严格模式下,全局作用域中的`this`值为`undefined`。在非严格模式下,全局作用域中的`this`值为全局对象(浏览器环境中为`window`对象,Node.js环境中为`global`对象)。此外,在严格模式下,不允许使用`call`、`apply`或`bind`将`this`值设置为`null`或`undefined`。
3. 禁止使用未来保留字: 严格模式中,不能将一些未来保留字(如`implements`、`interface`、`let`、`package`、`private`、`protected`、`public`、`static`和`yield`)用作变量名或函数名。
4. 禁止使用八进制字面量: 在严格模式下,不允许使用八进制字面量(如`0123`)。非严格模式下,八进制字面量是允许的。
5. 禁止删除变量、函数和函数参数: 严格模式中,使用`delete`操作符删除变量、函数和函数参数会引发语法错误(SyntaxError)。在非严格模式下,这样的操作是允许的,但实际上不会删除这些对象。
6. 限制函数参数的重复声明: 在严格模式下,如果一个函数具有多个相同名称的参数,将会抛出一个语法错误。非严格模式下允许这种重复声明,但只有最后一个参数值会生效。
7. 错误处理: 严格模式相较于非严格模式,更严格地处理某些类型的错误。例如,当试图修改只读属性、给不可扩展的对象添加属性或删除不可配置的属性时,严格模式会抛出类型错误(TypeError),而非严格模式下则会静默失败。
要启用严格模式,可以在脚本或函数开头添加`"use strict";`指令。这将对整个脚本或函数体中的代码启用严格模式。推荐使用严格模式编写代码,因为它可以帮助发现潜在的错误并避免一些不良的编程实践。
为什么0.1+0.2不等于0.3?
浮点数精度问题。JavaScript使用IEEE 754标准中规定的双精度浮点数(double-precision floating point)来表示数字。这种表示方法在大多数情况下都很有效,但有时会导致精度损失。
双精度浮点数只有有限的位数(64位)来表示数字,其中1位表示符号位,11位表示指数,以及52位表示尾数。当尝试表示某些数字(特别是十进制小数)时,它们的二进制表示可能是无限循环的,因此需要截断以适应有限的位数。这可能导致浮点数的近似值与实际值之间存在微小差异。
在本例中,0.1和0.2的二进制表示都是无限循环的,需要截断。当它们被截断并以双精度浮点数存储时,这两个数字的实际值与理论值略有不同。因此,当执行0.1 + 0.2时,结果也会有微小误差,与0.3的理论值不完全相等。