1. 1. DOM事件类
    1. 1.1. 事件级别
    2. 1.2. 事件类型
    3. 1.3. 事件流
    4. 1.4. DOM事件捕获的具体流程
    5. 1.5. Event对象的常见应用
    6. 1.6. 自定义事件
  2. 2. HTTP协议类
    1. 2.1. HTTP协议主要特点
    2. 2.2. HTTP报文组成
    3. 2.3. HTTP方法
    4. 2.4. POST和GET的区别
    5. 2.5. HTTP 状态码
    6. 2.6. 持久连接
    7. 2.7. 管线化
    8. 2.8. HTTP和HTTPS数据传输过程
    9. 2.9. HTTPS的工作原理
  3. 3. 函数
  4. 4. 原型链类
    1. 4.1. 创建对象的几种方法
    2. 4.2. 原型、构造函数、实例、原型链
    3. 4.3. 原型链的来源
    4. 4.4. 什么是构造函数
    5. 4.5. 什么是原型
    6. 4.6. 什么是原型链
    7. 4.7. instanceof
    8. 4.8. new 运算符
  5. 5. 面向对象
    1. 5.1. 类的声明
    2. 5.2. 构造函数
    3. 5.3. 类的继承
  6. 6. 通信类
    1. 6.1. 同源策略及限制
    2. 6.2. 前后端如何通信
    3. 6.3. 跨域通信的方式
  7. 7. 安全类
    1. 7.1. CSRF
      1. 7.1.1. 攻击流程
      2. 7.1.2. 防御
    2. 7.2. XSS
  8. 8. 算法
    1. 8.1. 排序
    2. 8.2. 堆栈、队列、链表
    3. 8.3. 递归
    4. 8.4. 波兰式和逆波兰式

DOM事件类

事件级别

级别 语法 备注
DOM0 element.onclick = function() {}
DOM2 element.addEventListener('click', function() {}, fasle) 第三个参数:
true 捕获阶段执行;
false 冒泡阶段执行。
简单理解,true 禁止向外冒泡,
false 反之
DOM3 element.addEventListener('keyup', function() {}, fasle)

DOM1标准没有制定与事件相关的内容;
DOM3 多了事件类型

事件类型

捕获;冒泡

事件流

image-20200208114319761

DOM事件捕获的具体流程

image-20200208115112905

Event对象的常见应用

方法/属性 作用
event.preventDefault() 阻止默认事件
event.stopPropagation() 阻止事件冒泡
event.stopImmediatePropagation() 如果有多个相同类型事件的事件监听函数绑定到同一个元素,当该类型的事件触发时,它们会按照被添加的顺序执行。如果其中某个监听函数执行了 event.stopImmediatePropagation() 方法,则当前元素剩下的监听函数将不会被执行
event.currentTarget 标识是当事件沿着 DOM 触发时事件的当前目标,指向事件绑定的元素
event.target 指向事件触发的元素

自定义事件

1
2
3
const eve = new Event('custome');
ev.addEventListener('custome', () => {});
ev.dispatchEvent(eve);
  • ev 表示dom节点
  • 可以使用CustomEvent 来代替Event ,两者的区别是CustomEvent 可以接收第二个参数,用来携带参数,用法与Event 完全相同。

HTTP协议类

HTTP协议主要特点

简单快速;灵活;无连接;无状态

HTTP报文组成

image-20200208123951397

HTTP方法

  • GET :获取资源
  • POST : 传输资源
  • PUT :更新资源
  • DELETE :删除资源
  • HEAD :获取报文首部

POST和GET的区别

  1. GET 参数通过URL传递,POST 放在Request body中活query string中
  2. GET 请求在URL中传递的参数有长度限制,POST无长度限制
  3. GET 请求参数会被完整保留在浏览器历史记录,POST 的参数不会保留
  4. GET 安全性不如POST,因为GET 参数直接暴露在URL上
  5. GET 请求只能进行URL编码,POST 有多种编码方式(JSON,formdata…)
  6. GET 在浏览器回退无害,而POST 会再次提交请求
  7. GET 产生的浏览器地址可以被收藏,而POST 不可以
  8. GET 请求会被浏览器主动缓存,而POST 不会,除非手动设置
  9. 。。。。。

HTTP 状态码

  • 1xx : 指示信息。表示请求已接收,继续处理
  • 2xx : 成功。表示请求已被成功接收
  • 3xx : 重定向。要完成请求必须进行更进一步的操作
  • 4xx : 客户端错误。请求有语法错误或请求无法实现
  • 5xx :服务器错误。服务器未能实现合法的请求

持久连接

HTTP 协议采用 “请求 – 应答” 模式,当使用普通模式,即非 Keep-Alive 模式时,每个请求/应答客户和服务器都要新建一个连接,完成之后立即断开连接(HTTP 协议为无连接协议)

当使用 Keep-Alive 模式(又称持久连接、连接重用)时,Keep-Alive 功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive 功能避免了建立或者重新建立连接。

管线化

在使用 持久连接 的情况下,某个连接上消息的传递类似于

image-20200208132042713

在使用 管线化 时,某个连接上的消息变成了类似这样

image-20200208132457090

即我把请求一次性打包发给你,你把响应也一次性打包返回给我

  1. 管线化机制通过持久连接完成,仅 HTTP/1.1 支持此技术
  2. 只有 GET 和 HEAD 请求可以进行管线化,而 POST 则有所限制
  3. 初次创建连接时不应启动管线机制,因为服务器不一定支持
  4. 管线化不会影响响应到来的顺序
  5. 。。。。。

HTTP和HTTPS数据传输过程

HTTP: 传统的 HTTP 报文是直接将报文信息传输给 TCP,然后 TCP 再通过 TCP 套接字发送给目的主机

HTTPS: HTTPS 是 HTTP 报文直接将报文信息传输给 SSL 套接字进行加密,SSL 加密后将加密后的报文发送给 TCP 套接字,然后 TCP 套接字再将加密后的报文信息发送给目的主机,目的主机将通过 TCP 套接字获取加密后的报文给到 SSL 套接字,SSL 解密后交付给对应进程。

HTTPS的工作原理

HTTPS 再传输数据之前需要客户端与服务端之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息,这次握手使用了非对称加密。TLS/SSL 协议不仅仅是一套加密传输协议,更是一件经过艺术家精心设计的艺术品,TLS/SSL 中使用了非对称加密,对称加密以及HASH算法。一次握手过程如下:

  1. 浏览器发出请求,将自己支持的一套加密规则发送给服务端。
  2. 服务端从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,加密公钥,以及证书颁发机构,证书过期时间等信息。
  3. 浏览器获得网站证书后需要进行以下操作
    1. 验证证书的合法性(证书颁发机构是否合法,证书中包含的网站地址与正在访问的网站地址是否一致,想证书颁发机构验证证书是否有效),如果证书受信任,浏览器地址栏会显示一个小锁头,否则会给出证书不受信的提示
    2. 如果证书受信,或者用户接受了不受信任的证书,浏览器会生成一串随机数的密码,并用证书中提供的公钥进行加密
    3. 使用约定好的HASH计算握手消息,并使用生成的随机数对消息对消息进行加密,最后将之前生成的所有信息发送给服务器。
  4. 服务器接收到浏览器发来的数据后,需要做一下操作:
    1. 使用自己的私钥将信息解密取出密码,使用密码解密浏览器发来的握手消息,并验证HASH是否与浏览器发来的一致。
    2. 使用密码加密一段握手消息,发送给浏览器
  5. 浏览器揭秘并计算握手消息的HASH,如果与服务器发来的HASH一致,此时握手结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密。

这里的浏览器与服务器互相发送握手消息并验证,目的是为了保证双方都获得了一致的密码,并且可以正常的加密解密数据,为后续真正的数据传输做一次测试。

img

函数

原型链类

创建对象的几种方法

  • 方法一 : 字面量

    1
    2
    const o1 = {name: 'o1'};
    const o2 = new Object({name: o2});
  • 方法二 :构造函数

    1
    2
    3
    4
    const M = function() {
    this.name = 'o3'
    }
    const o3 = new M();
  • 方法三 : Object.create()

    1
    2
    const P = {name: 'o4'};
    const o4 = Object.create(P);

原型、构造函数、实例、原型链

image-20200208140524379

原型链的来源

JavaScript 没有“子类”和“父类”的概念,也没有“类”(class)和“实例”(instance)的区分,全靠一种很奇特的“原型链”(prototype chain)模式,来实现继承。

之所以这样设计,是因为 Brendan Eich 最初设计 JavaScript 时,是为了实现网页和浏览器之间交互的一种简单的脚本语言,如果真的是一种简易的脚本语言,其实是不需要有“继承”机制的。但由于 JavaScript 中万物皆对象,必须有一种机制,将所有对象联系起来,所以,Brendan Eich 最后还是设计了“继承”。

什么是构造函数

构造函数:一种特殊的方法,主要用来在创建对象时初始化对象。每个构造函数都有 prototype(原型)属性

什么是原型

原型:每个函数都有 prototype(原型)属性,这个属性是一个指针,指向一个对象,这个对象的用途是包含特定类型的所有实例共享的属性和方法,即这个原型对象是用来给特定实例共享属性和方法的,而每个实例内部都有一个指向原型对象的指针。

什么是原型链

原型链:在 JavaScript 中,对象之间的继承关系,是通过 prototype 对象指向父类对象,父类的 prototype 指向父类的父类对象,如此层层递进,就构成了实例和原型的链条,我们称为原型链。

instanceof

image-20200208142452425

new 运算符

  1. 一个新对象被创建。它继承自foo.prototype(构造函数的原型)
  2. 构造函数被执行。执行的时候,相应的传参会被传入,同时上下文(this)会被指定为这个新实例。new foo 等同于new foo() ,只能用在不传递任何参数的情况
  3. 如果构造函数返回了一个“对象”,那么这个对象会取代整个new 出来的结果。如果构造函数没有返回对象,那么 new 出来的结果为步骤一创建的对象

面向对象

类的声明

  • ES5: function
  • ES6: class

构造函数

1
2
3
4
5
6
7
8
9
const puppet = {
rules: false
};
function Emperor() {
this.rules = true;
return puppet;
}
const emperor = new Emperor();
console.log(emperor.rules)

输出:false

如果构造函数有返回值且返回值为一个对象,此构造函数构造的实例就是这个返回值。

类的继承

  • 方法一 :借助构造函数实现继承

    1
    2
    3
    4
    5
    6
    7
    function Parent1() {
    this.name = 'parent1'
    }
    function Child1() {
    Parent1.call(this); // apply也可以 这行是重点
    this.type = 'child'
    }

    缺点:无法继承父类原型链上的方法,只能继承父类构造函数上的方法

  • 方法二 :借助原型链实现继承

    1
    2
    3
    4
    5
    6
    7
    function Parent1() {
    this.name = 'parent1'
    }
    function Child1() {
    this.type = 'child'
    }
    Child1.prototype = new Parent1();

    缺点1:Child1的原型链被new Parent1() 完全重写;

    缺点2:生成多个实例,多个实例原型链共用,一个实例被改,其他实例同步被改

  • 方法三 :组合方式

    1
    2
    3
    4
    5
    6
    7
    8
    function Parent1() {
    this.name = 'parent1'
    }
    function Child1() {
    Parent1.call(this);
    this.type = 'child'
    }
    Child1.prototype = new Parent1();

    对比方法二,父类构造函数中的方法和属性会被子类继承到子类的构造函数中,子类的原型链会继承父类的构造函数部分和原型链部分。调用父类的方法会先从子类的构造函数中查找。

    缺点:父类的构造函数会被执行两次

  • 方法四 :对方法三的优化

    1
    2
    3
    4
    5
    6
    7
    8
    function Parent1() {
    this.name = 'parent1'
    }
    function Child1() {
    Parent1.call(this);
    this.type = 'child'
    }
    Child1.prototype = Parent1.prototype;
  • 方法五 :继续优化

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function Parent1() {
    this.name = 'parent1'
    }
    function Child1() {
    Parent1.call(this);
    this.type = 'child'
    }
    Child1.prototype = Object.create(Parent1.prototype);
    Child1.prototype.constructor = Child1;

通信类

同源策略及限制

同源 :协议,端口,主机(域名)相同

同源策略 :同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

限制

  1. Cookie、LocalStorage和IndexDB无法读取
  2. 无法操作DOM
  3. 不能发送AJAX请求

前后端如何通信

  • Ajax 同源
  • WebSocket 不限制同源
  • CORS 支持同源;也支持跨域

跨域通信的方式

  • JSONP

    利用script 标签的异步加载 ;用户做某些操作的时候,通过js动态创建 script 标签, script 标签的src 属性填写请求域名拼接参数,后端返回一个函数的调用(函数名须于后端约定好),函数的入参即前端所需要的数据;

  • Hash

    url# 后面内容改变不会导致页面刷新; A页面通过iframe 嵌入页面B,A操作B的url,B监听# 内容的改变(使用window.onhashchage 方法)

  • postMessage :H5标准

    A和B两个窗口,A窗口拿到B窗口的引用,通过postMessage 向另一个窗口发送信息,另一窗口通过window.addEventListener('message', function() {}) 监听。

    1
    2
    3
    4
    5
    6
    7
    // 窗口A(https://A.com)向跨域的窗口B(https://B.com)发送信息
    Bwindow.postMessage(`data`, 'https://B.com')

    // B窗口监听
    window.addEventListener('message', function(data) {
    console.log('A窗口发过来的信息', data)
    })
  • WebSocket

  • CORS

    cors中间件,koa 框架可用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    const cors = async (ctx, next) => {
    //指定服务器端允许进行跨域资源访问的来源域。可以用通配符*表示允许任何域的JavaScript访问资源,但是在响应一个携带身份信息(Credential)的HTTP请求时,必需指定具体的域,不能用通配符
    ctx.set("Access-Control-Allow-Origin", "*");

    //指定服务器允许进行跨域资源访问的请求方法列表,一般用在响应预检请求上
    ctx.set("Access-Control-Allow-Methods", "OPTIONS,POST,GET,HEAD,DELETE,PUT");

    //必需。指定服务器允许进行跨域资源访问的请求头列表,一般用在响应预检请求上
    ctx.set("Access-Control-Allow-Headers", "x-requested-with, accept, origin, content-type, token");

    //告诉客户端返回数据的MIME的类型,这只是一个标识信息,并不是真正的数据文件的一部分
    ctx.set("Content-Type", "application/json;charset=utf-8");

    //可选,单位为秒,指定浏览器在本次预检请求的有效期内,无需再发送预检请求进行协商,直接用本次协商结果即可。当请求方法是PUT或DELETE等特殊方法或者Content-Type字段的类型是application/json时,服务器会提前发送一次请求进行验证
    ctx.set("Access-Control-Max-Age", 300);

    //可选。它的值是一个布尔值,表示是否允许客户端跨域请求时携带身份信息(Cookie或者HTTP认证信息)。默认情况下,Cookie不包括在CORS请求之中。当设置成允许请求携带cookie时,需要保证"Access-Control-Allow-Origin"是服务器有的域名,而不能是"*";如果没有设置这个值,浏览器会忽略此次响应。
    ctx.set("Access-Control-Allow-Credentials", true);

    //可选。跨域请求时,客户端xhr对象的getResponseHeader()方法只能拿到6个基本字段,Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。要获取其他字段时,使用Access-Control-Expose-Headers,xhr.getResponseHeader('myData')可以返回我们所需的值
    ctx.set("Access-Control-Expose-Headers", "myData");
    if (ctx.request.method === "OPTIONS") {
    ctx.response.status = 204
    }
    await next()
    }
    export default cors

安全类

CSRF

跨站请求伪造

攻击流程

image-20200208170451970

用户先访问了网站A,在网站A进行了登录,登陆成功后网站A的服务器将登录凭证存到了浏览器中。

之后用户又访问了网站B,网站B下发的文档中有引诱用户点击的内容,这个引诱的地址指向了网站A的某个链接,当用户点击这个引诱链接,就去去访问网站A的这个地址,由于用户在网站A之前进行了登录,所以这次访问就携带上了cookie,网站A的服务器接收到这个cookie,身份校验通过,就认为这个请求时这个用户的主动行为,就会去执行某些操作,而实际这个用户的这个行为时被诱导的。(刷粉丝量,刷点赞数。。。。。。)

防御

  • Token验证
  • Referer 验证 :验证来源
  • 隐藏令牌 :身份凭证添加在header中

XSS

原理 :向网站的页面中注入JS脚本

防御 :使注入的JS不可执行

算法

排序

preview

快速排序: https://segmentfault.com/a/1190000009426421

选择排序:https://segmentfault.com/a/1190000009366805

希尔排序:https://segmentfault.com/a/1190000009461832

堆栈、队列、链表

堆栈 队列 链表

递归

递归

波兰式和逆波兰式

波兰式和逆波兰式