关于异步
为什么要有异步?
- js单线程性。
- 由于部分操作的耗时性或者完成时的不确定性,我们不能阻塞地去等待这些操作的完成,所以就把这些操作单独拿出来,让他们在同步操作的最后执行,也就是所谓的异步操作。
异步的流程怎么控制
- callback
- 事件监听
事件可以解耦异步, 但是, 需要把所做的事情抽象出来成为一个事件才行, 而且事件还需要提前注册, 事件不可能没有注册的时候就收到事件通知, 先后顺序非常重要 - 发布/订阅
- Promises对象
promise 所取代的是 callback,把 callback 嵌套拍平拉成链,对于异步和回调的调用情况和流程有着非常严格的控制。
三个状态fulfilled,reject,pending - Co(Generator)
只谈co不谈Generator,是因为Generator并不是为解决异步流程控制而生的,而TJ大神用co把Generator和Thunk/Promise结合在一起提供了新的异步流程控制的方法。
参考 - async await
async await相当于 yield + co, 但是少了co的灵活, co不仅可以包装Promise还可以包装数组, 还可以包装thunk, 而await自动包装后的东西只能是原始值, 或者 Promise
但是async await更加语义化了, 而且由于没有 yield co的分离所造成, 必须把上下游完全改造成yield的东西才能进入现有应用, async await 直接就可以进入现有应用…这点特别赞!
async/await优点
web安全及防范
XSS(Cross-site scripting)
恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的
跨站脚本,对于用户输入、URL参数、第三方站点消息等,必须在使用前验证数据的安全性,并在展示时做正确转义。过滤一定要根据白名单,如果根据黑名单过滤,就会包含许多不确定性的风险。
1. 反射型xss
指浏览器在每次都要提交恶意数据,才能触发该漏洞
2. 存储型xss
指将代码一次性的提交到服务器
防范建议:
- 即便像 img 这种无害的标签,也要将允许配置的属性列出白名单,因为如果允许所有属性的话, onload 将可能用来执行跨站脚本。
- URLs 链接,比如超链接,也需要使用白名单过滤,可能的攻击方式是 javascript:,不过浏览器一般会对其进行安全验证。
- 页面插入的任何元素都有安全风险,比如自定提交的表单等。
- HttpOnly Cookie
CSRF(Cross-site request forgery)
如果允许用户提交表单,要验证用户的来源,因为表单是可以提交到任何域下的。网站可以通过提交隐藏的 token,或者检查请求的 Origin 标头预防此类攻击。
CSRF漏洞防御:
1. 验证HTTP Referer字段
2. 在请求地址中添加token并验证
在请求中放入攻击者所不能伪造的信息,并且该信息不存在于Cookie之中。
sql注入
就是拼接 SQL 参数。也就是将用于输入的查询参数,直接拼接在 SQL 语句中,导致了SQL 注入漏洞。
如果用户输入的是 2 or 1=1 进行sql注入攻击,那么看到,上面的语句(select id,no from user where id=2 or 1=1;)将user表中的所有记录都查出来了
防御:采用sql语句预编译和绑定变量,是防御sql注入的最佳方法
ddos(分布式拒绝服务攻击)
DdoS的攻击方式有很多种,最基本的DoS攻击就是利用合理的服务请求来占用过多的服务资源,从而使合法用户无法得到服务的响应。
http缓存
缓存的优点有:
- 减少了冗余的数据传输,节省了网费
- 减少了服务器的负担,大大提升了网站的性能
- 加快了客户端加载网页的速度
过程
- 浏览器会先获取该资源缓存的header信息,根据其中的expires和cahe-control判断是否命中强缓存,若命中则直接从缓存中获取资源,包括缓存的header信息,本次请求不会与服务器进行通信;
- 如果没有命中强缓存,浏览器会发送请求到服务器,该请求会携带第一次请求返回的有关缓存的header字段信息(Last-Modified/IF-Modified-Since、Etag/IF-None-Match),由服务器根据请求中的相关header信息来对比结果是否命中协商缓存,若命中,则服务器返回新的响应header信息更新缓存中的对应header信息,但是并不返回资源内容,它会告知浏览器可以直接从缓存获取;否则返回最新的资源内容
Expires: 该字段是http1.0时的规范,它的值为一个绝对时间的GMT格式的时间字符串。缺点,由于失效时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,就会导致缓存混乱。
Cache-Control: Cache-Control是http1.1时出现的header信息,主要是利用该字段的max-age值来进行判断,它是一个相对时间
- no-cache:使用协商缓存
- no-store: 不使用缓存
- public:可以被所用用户缓存
- private: 只允许被终端浏览器缓存,不允许被cdn等中继缓存器缓存
协商缓存
- last-modified/if-modified-since。浏览器第一次请求一个资源的时候,服务器返回的header中会加上Last-Modified(最后修改时间)。当浏览器再次请求该资源时,request的请求头中会包含If-Modify-Since,该值为缓存之前返回的Last-Modify。服务器收到If-Modify-Since后,根据资源的最后修改时间判断是否命中缓存。
- ETag/If-None-Match
为何还要etag。
- 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
- 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);
- 某些服务器不能精确的得到文件的最后修改时间。
服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。
| 缓存类型 | 状态码 |
|---|---|
| 强缓存 | 200(from cache) |
| 协商缓存 | 304(not modified) |
流程
先判断是否有缓存,然后检查是否新鲜。再进行服务器验证。
TCP和UDP的区别
UDP(用户数据报协议)
面向无连接,无流量控制拥塞避免,无重发机制,以报文为单位,首部开销8字节。
UDP主要用于那些对高速传输和实时性有较高要求的通信或广播通信。
TCP(传输控制协议)
面向连接,可靠传输,以字节为单位,首部开销20字节,全双工通信
可靠传输的原理: 1. 停止等待协议,确认和重传机制。自动重传ARQ协议。2. 连续ARQ协议(提高信道利用率)和滑动窗口机制
流量控制: 发送发速率不能太快,要让接收方来得及接收,发送方的发送窗口不能超过接收方给出的接收窗口数值。
拥塞控制: 防止过多数据注入网络中,这样可以使网络中的路由器或链路不致过载。
方法:
1. 慢开始和拥塞避免
由小到大逐渐增大(指数增长)发送窗口,到了慢开始门限值时,进行拥塞避免,把拥塞窗口线性增大。
2. 快重传和快恢复
- 快重传:接收方没收到一个失序的报文段,就发出重复确认,当发送方一连收到三个重复确认时,就立即重传对方尚未收到的报文段
- 快恢复:当收到三个重复确认时,执行乘性减小算法,然后把慢开始门限减半。
TCP三次握手和四次挥手
- 三次握手:
- 原因: 防止失效的报文再次发送到server端,造成server端一直等待,浪费资源。
- 过程:client发送SYN包到server端,server端发送ACK和SYN包到client端,client发送ACK
- 状态:1. SYN-SENT 2. SYC-RCVD 3. ESTABLISHED
- 四次挥手
- 原因:双向释放
- 过程: client发送FIN到server, server发送ACK到client,server发送FIN和ACK到client,client发送ACK到server
- 状态:1. FIN-WAIT-1 2. CLOSE-WAIT 3. FIN-WAIT-2 4. LAST-ACK 5. TIME-WAIT
ACK延迟确认机制
接收方在收到数据后,并不会立即回复ACK,而是延迟一定时间。一般ACK延迟发送的时间为200ms,但这个200ms并非收到数据后需要延迟的时间。系统有一个固定的定时器每隔200ms会来检查是否需要发送ACK包。这样做有两个目的。
1、这样做的目的是ACK是可以合并的,也就是指如果连续收到两个TCP包,并不一定需要ACK两次,只要回复最终的ACK就可以了,可以降低网络流量。
2、如果接收方有数据要发送,那么就会在发送数据的TCP数据包里,带上ACK信息。这样做,可以避免大量的ACK以一个单独的TCP包发送,减少了网络流量。
从一个url输入到页面加载完
- dns解析
先检查本地hosts,然后查询本地服务器,再递归或者迭代根域名服务器,顶级域名服务器,权限域名服务器。 - tcp三次连接
- http请求
- http响应
- tcp四次挥手
- 渲染html文档
性能优化
1、尽量减少HTTP请求次数
2、减少DNS查找次数
3、避免跳转
4、可缓存的AJAX
5、推迟加载内容
6、预加载
7、减少DOM元素数量
8、根据域名划分页面内容
9、使iframe的数量最小
10、不要出现404错误
11、使用内容分发网络
12、为文件头指定Expires或Cache-Control 13、Gzip压缩文件内容
14、配置ETag
15、尽早刷新输出缓冲
16、使用GET来完成AJAX请求
17、把样式表置于顶部
18、避免使用CSS表达式(Expression)
19、使用外部JavaScript和CSS
20、削减JavaScript和CSS
21、用代替@import
22、避免使用滤镜
23、把脚本置于页面底部
24、剔除重复脚本
跨域
- JSONP
原理:动态插入script标签,利用src属性可以跨域,方式是get,url后面加?callback=xxx,如果恰好有xxx函数,就可以收到参数然后作文章。 - document.domain
用于解决子域名不同。与iframe配合 - window.name+iframe
postMessage
两页面间通信window.postMessage(data, origin, source)cors
设置access-control-allow-origin:‘*’- 反向代理
readyState
0: 请求未初始化 open()尚未调用
1: 服务器连接已建立 open()已调用
2: 请求已接收 接收到头信息
3: 请求处理中 接受到响应主体
4: 请求已完成,且响应已就绪 响应完成
ajax源码
ajax({
url: "./TestXHR.aspx", //请求地址
type: "POST", //请求方式
data: { name: "super", age: 20 }, //请求参数
dataType: "json",
success: function (response, xml) {
// 此处放成功后执行的代码
},
fail: function (status) {
// 此处放失败后执行的代码
}
});
function ajax(options) {
options = options || {};
options.type = (options.type || "GET").toUpperCase();
options.dataType = options.dataType || "json";
var params = formatParams(options.data);
//创建 - 非IE6 - 第一步
if (window.XMLHttpRequest) {
var xhr = new XMLHttpRequest();
} else { //IE6及其以下版本浏览器
var xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
//接收 - 第三步
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
var status = xhr.status;
if (status >= 200 && status < 300) {
options.success && options.success(xhr.responseText, xhr.responseXML);
} else {
options.fail && options.fail(status);
}
}
}
//连接 和 发送 - 第二步
if (options.type == "GET") {
xhr.open("GET", options.url + "?" + params, true);
xhr.send(null);
} else if (options.type == "POST") {
xhr.open("POST", options.url, true);
//设置表单提交时的内容类型
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(params);
}
}
//格式化参数
function formatParams(data) {
var arr = [];
for (var name in data) {
arr.push(encodeURIComponent(name) + "=" + encodeURIComponent(data[name]));
}
arr.push(("v=" + Math.random()).replace(".",""));
return arr.join("&");
}
代理与网关的对比
代理连接的是两个或多个使用相同协议的应用程序,而网管连接的则是两个或多个使用不同协议的端点。网管扮演的是“协议转换器”的角色。
使用代理的好处
- 儿童过滤器
- 文档访问控制
- 安全防火墙
- web缓存
- 反向代理来提高访问慢速web服务器上公共内容时的性能。
https
在将http发送给tcp之前,先将其发送给一个安全层,对其进行加密。
- ssl记录协议:
- 主要完成分组和组合,压缩和解压缩,以及消息认证和加密等功能。
- ssl握手协议:
- 交换协议版本好
- 选择两端都了解的密码
- 对两端进行身份认证
- 生成临时的会话秘钥
过程
①客户端的浏览器向服务器传送客户端 SSL 协议的版本号,加密算法的种类,产生的随机数,以及其他服务器和客户端之间通讯所需要的各种信息。
②服务器向客户端传送 SSL 协议的版本号,加密算法的种类,随机数以及其他相关信息,同时服务器还将向客户端传送自己的证书。
③客户利用服务器传过来的信息验证服务器的合法性,服务器的合法性包括:证书是否过期,发行服务器证书的 CA 是否可靠,发行者证书的公钥能否正确解开服务器证书的“发行者的数字签名”,服务器证书上的域名是否和服务器的实际域名相匹配。如果合法性验证没有通过,通讯将断开;如果合法性验证通过,将继续进行第四步。
④用户端随机产生一个用于后面通讯的“对称密码”,然后用服务器的公钥(服务器的公钥从步骤②中的服务器的证书中获得)对其加密,然后将加密后的“预主密码”传给服务器。
⑤如果服务器要求客户的身份认证(在握手过程中为可选),用户可以建立一个随机数然后对其进行数据签名,将这个含有签名的随机数和客户自己的证书以及加密过的“预主密码”一起传给服务器。
⑥如果服务器要求客户的身份认证,服务器必须检验客户证书和签名随机数的合法性,具体的合法性验证过程包括:客户的证书使用日期是否有效,为客户提供证书的CA 是否可靠,发行CA 的公钥能否正确解开客户证书的发行 CA 的数字签名,检查客户的证书是否在证书废止列表(CRL)中。检验如果没有通过,通讯立刻中断;如果验证通过,服务器将用自己的私钥解开加密的“预主密码 ”,然后执行一系列步骤来产生主通讯密码(客户端也将通过同样的方法产生相同的主通讯密码)。
⑦服务器和客户端用相同的主密码即“通话密码”,一个对称密钥用于 SSL 协议的安全数据通讯的加解密通讯。同时在 SSL 通讯过程中还要完成数据通讯的完整性,防止数据通讯中的任何变化。
⑧客户端向服务器端发出信息,指明后面的数据通讯将使用的步骤⑦中的主密码为对称密钥,同时通知服务器客户端的握手过程结束。
⑨服务器向客户端发出信息,指明后面的数据通讯将使用的步骤⑦中的主密码为对称密钥,同时通知客户端服务器端的握手过程结束。
⑩SSL 的握手部分结束,SSL 安全通道的数据通讯开始,客户和服务器开始使用相同的对称密钥进行数据通讯,同时进行通讯完整性的检验。
数据库查询优化
1、数据库设计方面:
(1)建立索引
(2)分区(MySQL,如按时间分区)
(3)尽量使用固定长度字段和限制字段长度。(如VARCHAR2(10);优势:①降低物理存储空间 ②提高数据库处理速度 ③附带校验数据是否合法功能
2、在数据库I/O方面:
(1)增加缓冲区
(2)如果涉及表的级联,不同的表存储在不同磁盘上,以增加I/0速度
3、在SQL语句方面:
(1)优化SQL语句,减少比较次数
(2)限制返回条目数(mysql中使用limit)
闭包概念及应用场景
闭包就是指有权访问另一函数作用域的变量的函数
应用场景:
1. 代替全局变量
2. 在函数外或其他函数中访问某一函数内部的参数
3. 在函数执行之前为函数提供参数(setTimeout,setInterval)
String使用正则的方法
- search( ),返回第一个与之匹配的子串的起始位置,否则返回-1。忽略修饰符g
- replace(),第一个参数是正则表达式,第二个是要进行替换的字符串。如果在替换字符串中出现了$加数字,那么replace()将用与指定的表达式相匹配的文本来替换着两个字符。当为函数时,该函数的第一个参数是匹配模式的字符串。接下来的参数是与模式中的子表达式匹配的字符串,可以有 0 个或多个这样的参数。接下来的参数是一个整数,声明了匹配在 stringObject 中出现的位置。最后一个参数是 stringObject 本身。
- match(),返回的是一个由匹配结果组成的数组。如果不是全局检索,也返回一个数组,a[0]存放完整的匹配,a[n]存放$n的内容
- split( )返回数组。
regexp的方法
exec()方法对一个指定的字符串执行一个正则表达式,简言之,就是在一个字符串中执行匹配检索。如果没有匹配就返回null,但如果找到了匹配,返回一个数组,就像match()方法为非全局检索返回的数组一样。属性input引用的是正在检索的字符串,属性index包含了发生匹配的字符位置
test()方法:当exec返回的结果不是null时,test就返回true。
静态资源的缓存与更新
戳这里
简单来说,每次刷新页面,用的是浏览器缓存的静态资源。为了静态资源更新后,可以立刻访问最新静态资源,可以采用在链接后面加上时间戳,但是这样的话,每次就用不到静态资源了。所以对文件采用md5,只有文件更新时才改变链接,以便获取最新资源。
什么是闭包?* 堆栈溢出有什么区别? 内存泄漏? 那些操作会造成内存泄漏?怎么样防止内存泄漏?
闭包:就是能够读取其他函数内部变量的函数。
堆栈溢出:就是不顾堆栈中分配的局部数据块大小,向该数据块写入了过多的数据,导致数据越界,结果覆盖了别的数据。经常会在递归中发生。
内存泄露是指:用动态存储分配函数内存空间,在使用完毕后未释放,导致一直占据该内存单元。直到程序结束。指任何对象在您不再拥有或需要它之后仍然存在。
造成内存泄漏:
setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏。
闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)。全局变量在function结束后,不能被清除
防止内存泄露:
1、不要动态绑定事件;
2、不要在动态添加,或者会被动态移除的dom上绑事件,用事件冒泡在父容器监听事件;
3、如果要违反上面的原则,必须提供destroy方法,保证移除dom后事件也被移除,这点可以参考Backbone的源代码,做的比较好;
4、单例化,少创建dom,少绑事件。
垃圾回收机制
- 引用计数
当声明了一个变量并将一个引用类型赋值给该变量时,则这个值的引用次数就是1。相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数就减1。当这个引用次数变成0时,则说明没有办法再访问这个值了,因而就可以将其所占的内存空间给收回来。 - 标记清除
当变量进入执行环境是,就标记这个变量为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到他们。当变量离开环境时,则将其标记为“离开环境”。
一个template函数
function template(str) {
var reg = /<%=\s*([^%>]+)\s*%>/g;
return function(data) {
return str.replace(reg, function(a, b, c, d, e ) {
var regTrim = /\s*/g;
console.log(a,b,c)
return data[b.replace(regTrim, '')];
})
}
}
var m = template('nbb <%= name %> aaa <%= name %>')
console.log(m({name: 'lejunjie'}))
对于输入框的事件顺序
- keydown
- focus
- keypress
- input
- keyup(不能是tab,shift等字符)
- click
dns解析流程
- chrome搜索自身的dns缓存
- 搜索操作系统自身的dns缓存(浏览器没有找到缓存或者缓存已经失效)
- 读取本地的host文件
- 浏览器发起一个dns的一个系统调用
- 宽带运营商服务器查看本身缓存
- 运营商服务器发送一个迭代dns解析请求
本地域名服务器-》根域名服务器-》顶级域名服务器
本文探讨了异步编程的概念及其在JavaScript中的实现方法,包括callback、事件监听、发布/订阅模式、Promises、Co(Generator)等。此外,还介绍了常见的Web安全问题及其防范措施,如XSS、CSRF、SQL注入等。
2015

被折叠的 条评论
为什么被折叠?



