XMLHttpRequest 是一个API, 它为客户端提供了在客户端和服务器之间传输数据的功能。它提供了一个经过 URL 来获取数据的简单方式,而且不会使整个页面刷新。javascript
readyState
属性, 共有如下5种状态html
值 | 状态 | 描述 |
---|---|---|
0 | UNSENT | 未调用 open()方法 |
1 | OPENED | open()已被调用, 未调用send()方法 |
2 | HEADERS RECEIVED | send()方法已调用, 响应的状态和头部已返回 |
3 | LOADING | 加载响应体, responseText中已经获取了部分数据 |
4 | DONE | 整个请求过程已经完毕 |
须要提到做用域,做用域分全局做用域和局部做用域,外部变量属于全局做用域,函数内部变量属于局部做用域。 函数做用域是定义时肯定的。 内部函数能够访问外部函数的变量, 参数, 其它函数声明。 若是这个内部函数容许在包含的这个函数外被调用,就会造成一个闭包。java
利用闭包生成一个自增id函数node
function createIncId (seed) { seed = parseInt(seed) || 0; return function () { return seed++; } } var incFn1 = createIncId(100); var incFn2 = createIncId(10); incFn1(); // 100 incFn1(); // 101 incFn2(); // 10 incFn2(); // 11
首先,闭包是因为执行函数后返回的对象或函数拥有对外部函数的变量,参数和函数声明具备访问权。所以,在js的回收机制上,是会被标记这些变量,参数,函数声明引用(在定义时肯定哪些变量会被添加标记),在定时回收的时候不会考虑将这些占用的内存回收。若是咱们将返回的对象或函数设置为null, 那么就失去了对内部变量的控制,就会被回收。web
下面是一个简单的例子 在线测试ajax
var createClouse = function () { var args = [].slice.call(arguments, 0); return { // 保存了对 args 的 引用 getValue: function (index) { return args[index] || undefined; }, getIndex: function (val) { return args.findIndex(function (arg) { return val === arg; }); } } } var clouse = createClouse({}, [], '', null, undefined, false, 0); alert(clouse.getIndex(undefined)); // 一旦clouse的引用不存在, 则该对象被标记为回收状态 clouse = null;
采用 Mark-and-sweep
(标记扫描)算法算法
要了解如何预防内存泄漏,须要了解对象的基本生命周期。对象生命周期, JS为引用类型分配适当的内存, 从分配的开始起垃圾回收器会不断对该对象进行评估,检查是否属于有效的对象。
垃圾回收器按期扫描对象, 会将引用数量为0或将对象惟一引用是循环到对象进行回收。chrome
内存泄露方式1: 闭包json
var theThing = null; var replaceThing = function () { var originalThing = theThing; var unused = function () { if (originalThing) { console.log('hi'); } }; theThing = { longStr: new Array(1000000).join('*'), someMethod: function () { console.log('some message'); } }; // 显示标记释放内存 // originalThing = null; }; setInterval(replaceThing, 1000);
若是一直执行的话,能够在chrome工具栏 memory下给 Heap 拍几张快照,会发现内存会每隔1s钟不断增长跨域
缘由在于theThing
的 someMethod
与 unused
都为同一个父做用域, unused
引用了originalThing
,someMethod
与 unsued
共享闭包范围. 则对originalThing
引用强制保持活动状态防回收.
若是在replaceThing
后面加入 originalThing = null
, 则循环后不会使内存增加
内存泄露方式2: 意外的全局变量
function foo () { // 意外的绑定在全局 window.bar 变量上 bar = 'global value'; } foo();
通常来讲,尽可能少用全局变量. 而多用户函数声明运行建立一个私有的函数做用域. 局部变量会在执行后进行释放. 使用 'use strict'
防止出现隐式定义全局变量的状况
内存泄露方式3: 被遗忘的计时器或回调函数
var someResource = getData(); var interval = setInterval(function() { var node = document.getElementById('Node'); if(node) { // Do stuff with node and someResource. node.innerHTML = JSON.stringify(someResource)); } else { // clearInterval(interval); } }, 1000);
一旦node
节点不存在, someResource
则成为了避免须要的引用,因为setInterval
定时器仍然存在的关系, 则没法回收someResource
的数据. 解决办法, 使用clearInterval
回收定时器
内存泄露方式4: 脱离 DOM 的引用
var elements = { button: document.getElementById('button'), image: document.getElementById('image'), text: document.getElementById('text') }; function doStuff() { image.src = 'http://some.url/image'; button.click(); console.log(text.innerHTML); // Much more logic } function removeButton() { // The button is a direct child of body. document.body.removeChild(document.getElementById('button')); // At this point, we still have a reference to #button in the global // elements dictionary. In other words, the button element is still in // memory and cannot be collected by the GC. }
DOM的引用在文档中被删除,可是在js内还有存在被引用, 则也不会产生垃圾回收。
DOM的节点绑定事件后若是直接删除DOM,但事件未被删除,这也会形成泄露。
首先要了解一下同源策略,是浏览器核心,基本的安全功能更。限制了一个源中的文本合伙脚本加载来自其余源的资源.
同源的意思: 同一个协议, 同一个域名, 同一个端口.
跨域方式1: 主域相同两个子域进行跨域. 设置 document.domain
好比: http://m.liylblog.com
与 http://www.liylblog.com
设置 http://m.liylblog.com/a.html
和 http://m.liylblog.com/b.html
的 document.domain
为liylblog.com
www.html 脚本
var getDomainIframe = (function (domain, src) { document.domain = domain; var ifr = document.createElement('iframe'); ifr.src = src; ifr.style.display = 'none'; document.body.appendChild(ifr); var promise = new Promise (function (resolve, reject) { ifr.onload = function () { ifr.onload = null; resolve(ifr.contentWindow); }; }); return function () { return promise; } })('liylblog.com', 'http://m.liylblog.com/public/examples/2017/cros_domain/diff_subdomain/m.html'); function getData (xhr, fn) { xhr.open('GET', 'http://m.liylblog.com/public/examples/2017/cros_domain/diff_subdomain/m_data.json', true); xhr.onreadystatechange = function () { if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) { fn && fn(xhr.responseText); } } xhr.send(); } document.querySelector('#btn').addEventListener('click', function () { getDomainIframe().then(function (win) { var xhr = new win.XMLHttpRequest(); getData(xhr, function (data) { document.querySelector('#console').innerHTML = data; }); }); }, false);
m.html 脚本
document.domain = 'liylblog.com';
原理:
获取到 m.html 的window
对象, 则能够利用这个window对象下的 XMLHttpRequest
API对 m.liylblog.com
的资源进行ajax请求
跨域方式2: window.postMessage
HTML5新增的postMessage方法, 能够实现跨文档消息传输, 经过绑定window.addEventListner('message') 事件来监听发送文档消息传输内容。
跨域方式3: proxy 服务端代理
将要请求的地址以参数的方式发送给同域的服务器,由服务器代理请求目标地址
跨域方式4: jsonp 动态插入脚本
利用script脚本动态插入并执行的特性, 将请求地址存放至script
的src
属性中,当onload
加载完毕后执行脚本。
跨域方式5:CORS
跨域资源共享( CORS )机制容许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。浏览器支持在 API 容器中(例如 XMLHttpRequest 或 Fetch )使用 CORS,以下降跨域 HTTP 请求所带来的风险。
跨域资源共享标准新增了一组 HTTP 首部字段,容许服务器声明哪些源站有权限访问哪些资源。
规范要求,对那些可能对服务器数据产生反作用的 HTTP 请求方法, 进行OPTIONS方法 预检查请求(preflight request)
重绘
重绘是在一个元素的外观被改变,但没有改变布局的状况下发生的,如改变了visibility、outline、background等。当repaint发生时,浏览器会验证DOM树上全部其余节点的visibility属性。
回流
当元素改变的时候,将会影响文档内容或结构,或元素位置,此过程称为 Reflow。
何时会致使回流发生:
PS: 回流一定引发重绘
setTimeout
与 setInterval
主要经过定时任务的方式,执行修改DOM UI的代码, 从而交给UI线程进行处理渲染. 若是前面有了任务队列,则执行完前面的任务队列后再执行动画任务。
requestAnimationFrame
采用系统时间间隔,保持最佳绘制效率,不会由于间隔时间太短,形成过分绘制,增长开销;也不会由于间隔时间太长,使用动画卡顿不流畅,让各类网页动画效果可以有一个统一的刷新机制,从而节省系统资源,提升系统性能,改善视觉效果。
requestAnimationFrame
优势:
requestAnimationFrame
会把每一帧中的全部DOM操做集中起来,在一次重绘或回流中就完成,而且重绘或回流的时间间隔牢牢跟随浏览器的刷新频率requestAnimationFrame
将不会进行重绘或回流,这固然就意味着更少的CPU、GPU和内存使用量requestAnimationFrame
是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,而且若是页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销请求过程: - 请求行 HTTP版本号 - 请求首部 响应过程: - 响应HTTP版本号 响应状态码 响应状态 - 响应首部 - 响应实体
每个请求打开一个链接,请求结束后会关闭链接. 响应的对象本省能够是任何类型, HTML 文件,文本文件,图片,其它格式内容。 经过响应头部Content-Type 指定。
简单的请求
# telnet website.org 80 > GET /rfc/rfc1945.txt HTTP/1.0 > 两次回车
相比于HTTP1.0
, HTTP1.1
多了比较多的性能优化。
第一次HTTP请求文档成功后, 还会利用现有的链接发送一次请求获取 favicon.png
网站缩略图标. 若是任意一方想要停止链接,均可以发送 Connection: closed
关闭链接。
ALPN协议(应用层协商协议)
浏览器在创建TLS链接时,告诉服务器自身支持HTTP1.1
和HTTP2.0
协议. 服务器端获得信息后,也告诉浏览器自身支持HTTP2.0
协议。因而将协议转换成HTTP2.0。接下来经过HTTP2.0进行通讯。
基于HTTP的协商过程
HTTP Upgrade request GET / HTTP/1.1 host: nghttp2.org connection: Upgrade, HTTP2-Settings upgrade: h2c /*发起带有HTTP2.0 Upgrade头部的请求*/ http2-settings: AAMAAABkAAQAAP__ /*客户端SETTINGS净荷*/ user-agent: nghttp2/1.9.0-DEV HTTP Upgrade response HTTP/1.1 101 Switching Protocols /*服务端赞成升级到HTTP 2.0*/ Connection: Upgrade Upgrade: h2c HTTP Upgrade success /*协商完成*/
HTTP协议的缓存方式 主要分为强制缓存
和 协商缓存
- Pragma 1.0 - Expires - Cache-Control
OSI七层模型
协议层 | 传输方式 |
---|---|
物理层 | 传输二进制比特流 |
数据链路层 | 数据帧 (frame) |
网络层 | 数据包 (packet) |
传输层 | 数据段 (segment) |
会话层 | 管理主机之间的会话进程(socket) |
表示层 | 数据的加密、压缩、格式转换 |
应用层 | 报文消息(message) |
TCP/IP 协议栈
协议层 | 传输方式 |
---|---|
网络接口层 | 以太网, WIFI |
网络互连层 | IP, 对应主机IP, 发送数据包 |
传输层 | TCP, UDP ,对应端口, |
应用层 | HTTP,FTP, DNS |
TCP(传输控制协议)是一种面向链接的、可靠的、基于字节流的传输层通讯协议
UDP(用户数据报协议)是OSI参考模型中一种无链接的传输层协议,提供面向事务的简单不可靠信息传送服务。
HTTP,FTP,TELENET, SSH 属于TCP, ping命令属于 UDP
lsof
查找哪些端口占用的进程
sudo lsof -i:80
查找使用80端口的进程lsof -u www
查找用户www
的进程打开的文件netstat
显示与IP、TCP、UDP和ICMP协议相关的统计数据
netstat -lntp
查看开启了哪些端口top
查看CPU显示情况
top -u www
查看用户www
的的CPU 内存使用状况pmap
根据进程查看内存状况free
可用内存大小
free -m
MB为单位free -g
GB为单位-------------------------分割线-------------------------
问题的答案会不按期补全
欢迎你们指正,能学到东西就是好的