JavaScript
XMLHttpRequest介绍以及它的readyState状态码
XMLHttpRequest 是一个API, 它为客户端提供了在客户端和服务器之间传输数据的功能。它提供了一个通过 URL 来获取数据的简单方式,并且不会使整个页面刷新。
readyState
属性, 共有以下5种状态
值 | 状态 | 描述 |
---|---|---|
0 | UNSENT | 未调用 open()方法 |
1 | OPENED | open()已被调用, 未调用send()方法 |
2 | HEADERS RECEIVED | send()方法已调用, 响应的状态和头部已返回 |
3 | LOADING | 加载响应体, responseText中已经获取了部分数据 |
4 | DONE | 整个请求过程已经完毕 |
如何形容js的闭包
需要提到作用域,作用域分全局作用域和局部作用域,外部变量属于全局作用域,函数内部变量属于局部作用域。 函数作用域是定义时确定的。 内部函数可以访问外部函数的变量, 参数, 其它函数声明。 如果这个内部函数允许在包含的这个函数外被调用,就会形成一个闭包。
利用闭包生成一个自增id函数
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闭包的内存如何释放
首先,闭包是由于执行函数后返回的对象或函数拥有对外部函数的变量,参数和函数声明具有访问权。因此,在js的回收机制上,是会被标记这些变量,参数,函数声明引用(在定义时确定哪些变量会被添加标记),在定时回收的时候不会考虑将这些占用的内存回收。如果我们将返回的对象或函数设置为null, 那么就失去了对内部变量的控制,就会被回收。
下面是一个简单的例子 在线测试
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;
JavaScript的内存回收机制
采用 Mark-and-sweep
(标记扫描)算法
- 创建"根"列表, 保存引用的全局变量。 在浏览器中, window 对象总是存在的, window对象下的对象变量总是存在,所以不会被标记回收。
- 从“根”可到达的一切子节点不会被标记回收。
- 所有未被标记为活动的内存块都可以被标记,交由垃圾回收器进行回收。
JavaScript什么情况下会出现内存溢出, 如何防范
要了解如何预防内存泄漏,需要了解对象的基本生命周期。对象生命周期, JS为引用类型分配适当的内存, 从分配的开始起垃圾回收器会不断对该对象进行评估,检查是否属于有效的对象。
垃圾回收器定期扫描对象, 会将引用数量为0或将对象唯一引用是循环到对象进行回收。
内存泄露方式1: 闭包
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)
重绘(repaint)与回流(reflow)
重绘
重绘是在一个元素的外观被改变,但没有改变布局的情况下发生的,如改变了visibility、outline、background等。当repaint发生时,浏览器会验证DOM树上所有其他节点的visibility属性。
回流
当元素改变的时候,将会影响文档内容或结构,或元素位置,此过程称为 Reflow。
什么时候会导致回流发生:
- 改变窗口大小
- 改变文字大小
- 添加/删除样式表
- 内容的改变,(用户在输入框中写入内容也会)
- 激活伪类,如:hover
- 操作class属性
- 脚本操作DOM
- 计算offsetWidth和offsetHeight
- 设置style属性
PS: 回流必定引起重绘
setTimeout, setInterval, requestAnimationFrame 区别
setTimeout
与 setInterval
主要通过定时任务的方式,执行修改DOM UI的代码, 从而交给UI线程进行处理渲染. 如果前面有了任务队列,则执行完前面的任务队列后再执行动画任务。
requestAnimationFrame
采用系统时间间隔,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;也不会因为间隔时间太长,使用动画卡顿不流畅,让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。
requestAnimationFrame
优点:
-
requestAnimationFrame
会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率 - 在隐藏或不可见的元素中,
requestAnimationFrame
将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量 -
requestAnimationFrame
是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销
HTTP协议
协议介绍
请求过程:
- 请求行 HTTP版本号
- 请求首部
响应过程:
- 响应HTTP版本号 响应状态码 响应状态
- 响应首部
- 响应实体
HTTP 1.0
每一个请求打开一个连接,请求结束后会关闭连接. 响应的对象本省可以是任何类型, HTML 文件,文本文件,图片,其它格式内容。 通过响应头部Content-Type 指定。
简单的请求
# telnet website.org 80
> GET /rfc/rfc1945.txt HTTP/1.0
> 两次回车
HTTP 1.1
相比于HTTP1.0
, HTTP1.1
多了比较多的性能优化。
- 持久连接
- 分块编码传输
- 字节范围请求
- 增强缓存机制
- 传输编码请求管道
第一次HTTP请求文档成功后, 还会利用现有的连接发送一次请求获取 favicon.png
网站缩略图标. 如果任意一方想要中止连接,都可以发送 Connection: closed
关闭连接。
HTTP 2.0
协议升级方式
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七层模型和 TCP/IP四层模型
OSI七层模型
协议层 | 传输方式 |
---|---|
物理层 | 传输二进制比特流 |
数据链路层 | 数据帧 (frame) |
网络层 | 数据包 (packet) |
传输层 | 数据段 (segment) |
会话层 | 管理主机之间的会话进程(socket) |
表示层 | 数据的加密、压缩、格式转换 |
应用层 | 报文消息(message) |
TCP/IP 协议栈
协议层 | 传输方式 |
---|---|
网络接口层 | 以太网, WIFI |
网络互连层 | IP, 对应主机IP, 发送数据包 |
传输层 | TCP, UDP ,对应端口, |
应用层 | HTTP,FTP, DNS |
TCP与UDP区别
TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议
- 面向连接
- 传输可靠
- 保准传输顺序
UDP(用户数据报协议)是OSI参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。
- 面向非连接
- 传输不可靠
- 速度非常快
HTTP,FTP,TELENET, SSH 属于TCP, ping命令属于 UDP
解释一下TCP的三次握手和四次挥手
Linux
查找端口服务对应的进程
-
lsof
查找哪些端口占用的进程-
sudo lsof -i:80
查找使用80端口的进程 -
lsof -u www
查找用户www
的进程打开的文件
-
-
netstat
显示与IP、TCP、UDP和ICMP协议相关的统计数据-
netstat -lntp
查看开启了哪些端口
-
查看内存占用和CPU使用的命令
-
top
查看CPU显示状况-
top -u www
查看用户www
的的CPU 内存使用情况
-
-
pmap
根据进程查看内存情况 -
free
可用内存大小-
free -m
MB为单位 -
free -g
GB为单位
-
PHP
单例模式
实现远程加载图片资源, 考虑refer的情况
PHP的内存回收机制
算法
- 常见排序算法
- 快速排序算法的时间复杂度
- 如何实现二分排序
引用文章
-------------------------分割线-------------------------
问题的答案会不定期补全
欢迎大家指正,能学到东西就是好的
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。