OSI
OSI是Open System Interconnect的缩写,意为开放式系统互联。其各个层次的划分遵循下列原则:
(1)同一层中的各网络节点都有相同的层次结构,具有同样的功能。
(2)同一节点内相邻层之间通过接口进行通信。
(3)七层结构中的每一层使用下一层提供的服务,并且向其上层提供服务。
(4)不同节点的同等层按照协议实现对等层之间的通信。
HTTP和HTTPS
请求方法,状态码,HTTPS传输数据的流程
UDP和TCP
TCP应用:
(1)FTP:文件传输协议;
(2)SSH:安全登录、文件传送(SCP)和端口重定向;
(3)Telnet:不安全的文本传送;
(4)SMTP:简单邮件传输协议Simple Mail Transfer Protocol (E-mail);
(5)HTTP:超文本传送协议 (WWW);
UDP应用:
流媒体,实时游戏,物联网,QQ文件传输语音视频
对称加密和非对称加密
对称加密指的就是加密和解密使用同一个秘钥。更不安全
非对称加密指的是:加密和解密使用不同的秘钥,一把作为公开的公钥,另一把作为私钥。公钥加密的信息,只有私钥才能解密。私钥加密的信息,只有公钥才能解密。效率更低
XSS和CSRF
Cross-Site Scripting(跨站脚本攻击)简称 XSS,是一种代码注入攻击。
跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的 Web 应用程序上执行非本意的操作的攻击方法。
攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作
跨域
1、jsonp的原理就是利用<script>
标签没有跨域限制,通过<script>
标签src属性,发送带有callback参数的GET请求,服务端将接口返回数据拼凑到callback函数中,返回给浏览器,浏览器解析执行,从而前端拿到callback函数返回的数据。
2、CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
3、nginx:a网站向b网站请求1.js文件时,向b网站发送一个获取的请求,nginx根据配置文件接收这个请求,代替a网站向b网站来请求这个资源,nginx拿到这个资源后再返回给a网站,以此来解决了跨域问题。
4、postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。
强缓存和协商缓存
都是从客户端缓存中读取资源;区别是强缓存不会发请求,协商缓存会发请求。
强缓存: 通过http的response header中的Cache-Control和Expire两个字段控制。
主要看Cache-Control:
private:仅浏览器可以缓存
public:浏览器和代理服务器都可以缓存
max-age=xxx:过期时间
no-cache:不进行强缓存
no-store:不强缓存,也不协商缓存
强缓存步骤:1,第一次请求文件时,缓存中没有该信息,直接请求服务器。
2,服务器返回请求的文件,并且http response header中cache-control为max-age=xxx
3,再次请求该文件时,判断是否过期,如果没有过期,直接读取本地缓存,如果已经过期了,则进行协商缓存。
协商缓存:它的触发条件有两点、
第一点是 Cache-Control 的值为 no-cache,则会促发协商缓存。
第二点是 max-age 过期了,触发协商缓存。
当属性值为对象类型时,只拷贝了对象数据的引用,导致新旧数据没有完全分离,还会互相影响。array.concat()或者array.slice() 是特殊的实现数组浅拷贝的方式。
判断JS数据类型的基本方法
typeof运算符,
instanceof操作符(基于原型链),
Object.prototype.toString方法。
this的指向问题
- 全局作用域、普通函数以及定时器中的this指向全局对象window
- 方法中的this指向的是调用它的对象
- 构造函数中的this指向构造函数的实例
- 箭头函数中没有绑定this,this为最近外层作用域下有定义的this
- call、apply、bind可改变this指向
JS运行机制
JS是单线程语言
宏任务:1. script (可以理解为外层同步代码)2. setTimeout/setInterval3. UI rendering/UI事件4. postMessage,MessageChannel5. setImmediate,I/O(Node.js)
微任务:1. Promise2.process.nextTick(Node.js) 3. Object.observe(已废弃;Proxy 对象替代)4. MutaionObserver
Event Loop(事件循环)中,每一次循环称为 tick,
执行顺序:先执行同步代码,遇到异步宏任务则将异步宏任务放入宏任务队列中,遇到异步微任务则将异步微任务放入微任务队列中,当所有同步代码执行完毕后,再将异步微任务从队列中调入主线程执行,微任务执行完毕后再将异步宏任务从队列中调入主线程执行,一直循环直至所有任务执行完毕。
javascript垃圾回收机制原理:
标记清除,引用计数
JS中的数组
数组本来应该是一个连续的内存分配,但是在Javascript中不是连续分配的,而是类似哈希映射的方式存在的。
对于上述的实现方式,熟悉数据结构的同学应该知道,对于读取操作,哈希表的效率并不高,而修改删除的效率比较高。
现在浏览器为了优化其操作,对数组的创建时候的内存分配进行了优化:
对于同构的数组,也就是,数组中元素类型一致,会创建连续的内存分配
对于不同构数组,按照原来的方式创建。
如果你想插入一个异构数据,那么就会重新解构,通过哈希映射的方式创建
map()和forEach()的区别
- 能用
forEach()
做到的,map()
同样可以。反过来也是如此。 -
map()
会分配内存空间存储新数组并返回,forEach()
不会返回数据。 -
forEach()
允许callback
更改原始数组的元素。map()
返回新的数组。 -
cookie、sessionStorage和localStorage
如何创建BFC
body 根元素
浮动元素:float 除 none 以外的值
绝对定位元素:position (absolute、fixed)
display 为 inline-block、table-cells、flex
overflow 除了 visible 以外的值 (hidden、auto、scroll)
(常用于解决CSS高度坍塌)
let、var、const
1.var声明的变量会挂载在window上,而let和const声明的变量不会
2.var声明变量存在变量提升,let和const不存在变量提升
3.let和const声明形成块作用域
4.同一作用域下let和const不能声明同名变量,而var可以
5.const一旦声明必须赋值,不能使用null占位;声明后不能再修改 ;如果声明的是复合类型数据,可以修改其属性
声明 提升
1:所有的声明都会提升到作用域的最顶上去。
2:同一个变量只会声明一次,其他的会被忽略掉。
3:函数声明的优先级高于变量声明的优先级,并且函数声明和函数定义的部分一起被提升。
垂直居中
- 设定行高(line-height)
- 添加伪元素(vertical-align)
- calc动态计算
- 使用表格或假装表格
- transform
- 绝对定位(上级position)
- 使用Flexbox
-
CSS选择器优先级
内联样式>内部样式>外部样式>ID选择器>类选择器and伪类选择器>标签(元素)选择器and伪元素选择器>通配符选择器
回流reflow 重绘repaint
·使用class代替style,减少style的使用
·使用resize、scroll时进行防抖和节流处理,这两者会直接导致回流
·使用visibility替换display:none,因为前者只会引起重绘,后者会引发回流
·批量修改元素时,可以先让元素脱离文档流,等修改完毕后,再放入文档流
·避免触发同步布局事件,我们在获取offsetWidth这类的属性时,可以使用变量将查询结果存起来,避免多次查询,每次对offset / scroll /client等属性进行操作时都会触发回流
·对于复杂动画效果,使用绝对定位让其脱离文档流,复杂动画效果会频繁的触发回流和重绘,我们可以将动画元素设置绝对定位从而脱离文档流避免反复回流重绘。
尾调用优化
尾调用之所以与其他调用不同,就在于它的特殊的调用位置。函数调用会在内存形成一个"调用记录",又称"调用帧"(call frame),保存调用位置和内部变量等信息。
如果在函数A的内部调用函数B,那么在A的调用记录上方,还会形成一个B的调用记录。等到B运行结束,将结果返回到A,B的调用记录才会消失。
如果函数B内部还调用函数C,那就还有一个C的调用记录栈,以此类推。所有的调用记录,就形成一个"调用栈"(call stack)。
而尾调用时,由于是函数的最后一步操作,所以不需要保留外层函数的调用记录,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用记录,取代外层函数的调用记录就可以了。
只保留内层函数的调用记录。
如果所有函数都是尾调用,那么完全可以做到每次执行时,调用记录只有一项,这将大大节省内存。
节流 防抖
- 都可以通过使用
setTimeout
实现 - 目的都是,降低回调执行频率。节省计算资源
防抖在连续的事件,只需触发一次回调的场景有:
- 搜索框搜索输入。只需用户最后一次输入完,再发送请求
- 手机号、邮箱验证输入检测
- 窗口大小
resize
。只需窗口调整完成后,计算窗口大小。防止重复渲染。
let btn=document.getElementsByTagName('button')[0];
let timeout;
btn.onclick=()=>{
clearTimeout(timeout);
timeout=setTimeout(()=>{
console.log("ADD");//需要执行的代码
},2000);
}
节流在间隔一段时间执行一次回调的场景有:
- 滚动加载,加载更多或滚到底部监听
- 搜索框,搜索联想功能
let btn=document.getElementsByTagName('button')[0];
let bol=true;
btn.onclick=()=>{
if(bol){
console.log("ADD");//需要执行的代码
bol=false;
}else{
return ;
}
setTimeout(()=>{
bol=true;
},2000)
}
JavaScript阻止修改对象的三种方式
防止扩展:
禁止为对象添加属性和方法。但已存在的属性和方法可以被修改或删除。
实施操作:Object.preventExtensions()
检测是否应用该操作:Object.isExtensible()
密封:
禁止为对象删除已存在的属性和方法。被密封的对象也是不可扩展的。
实施操作:Object.seal()
检测是否应用该操作:Object.isSealed()
冻结:
禁止为对象修改已存在的属性和方法。所有字段均只读。被冻结的对象也是不可扩展和密封的。
实施操作:Object.freeze()
检测是否应用该操作:Object.isFrozen()
加载阻塞
defer 特点
- 对于
defer
的script
,浏览器会继续解析html
,且同时并行下载脚本,等DOM
构建完成后,才会开始执行脚本,所以它不会造成阻塞; -
defer
脚本下载完成后,执行时间一定是DOMContentLoaded
事件触发之前执行; - 多个
defer
的脚本执行顺序严格按照定义顺序进行,而不是先下载好的先执行;
async 特点
- 对于
async
的script
,浏览器会继续解析html
,且同时并行下载脚本,一旦脚本下载完成会立刻执行;和defer
一样,它在下载的时候也不会造成阻塞,但是如果它下载完成后DOM
还没解析完成,则执行脚本的时候是会阻塞解析的; -
async
脚本的执行 和DOMContentLoaded
的触发顺序无法明确谁先谁后,因为脚本可能在DOM
构建完成时还没下载完,也可能早就下载好了; - 多个
async
,按照谁先下载完成谁先执行的原则进行,所以当它们之间有顺序依赖的时候特别容易出错。
em rem
em相对于父元素,rem相对于根元素
像素(px):用于元素的边框或定位。
em/rem:用于做响应式页面
css设置0.5px的border
1、transform:scale(0.5);
利用的是 transform 缩放功能,将 1px 缩放一半,同时利用定位,将伪元素覆盖整个 div 元素,从而达到伪元素与本身元素的合并效果。
2、svg
原理是利用SVG的描边属性为1物理像素(物理像素最低也必须得有1,不然什么也看不见了),是高清屏的0.5px。
JS浮点数精度问题
把小数放大为整数(乘),进行算术运算,再缩小为小数(除)