知识梳理(一)

news2024/12/25 8:52:21

HTTPS握手过程

https的核心的技术:使用非对称加密传输对称加密的密钥,然后用对称加密通信

TLS

http--超文本传输协议,是以前并且沿用至今的网页协议。

缺点:http属于明文传输

HTTP的明文传输带来的问题是无法防止中间人截获、盗取和篡改信息,从你的路由器、运营商到对方服务器,中间每一步都是明文。

数据无价,所以为了实现保证数据的安全,在http的基础上,发展出了https。

http属于应用层,基于TCP/IP参考模型,为了实现传输数据的安全,在应用程和传输层之间添加了一层SSL/TLS,实现数据的加密

样式大概是这样。

 

TLS解决http的风险分为三步:信息加密、校验机制以及身份验证

TLS的交互过程,见下图。

RSA密钥协商握手过程 

第一次握手

先是客户端发出连接请求,即client hello包。

这个包里面主要包含了三个内容:TLS version(TLS版本)、Client Random(客户端随机数)、Cipher Suites(密码套件)

版本就是我客户端方面所支持的版本号,用于和服务端协商的,旨在相互适应。

随机数这个是客户端的,用于后面的加密。

密码套件这个是客户端想要使用的加密方法,也是用于协商的,这里是RSA。

第二次握手

服务端收到了客户端的hello包,会先回应一个Server hello包回去。

里面记录的内容和客户端发来的内容不尽相同,也是版本、随机数和密码套件,版本和套件协商,随机数用于加密。

然后服务端将会再发出下一个包Server Certificate

这个包里面包含一个数字证书,旨在证明自己服务端的身份

然后再发送Server Hello Done,告诉客户端hello结束,可以下一步了。

第三次握手

收到消息的客户端就开始忙活起来了,先是协商内容,没问题,看证书。

证书里面存在两个Hash值,第一个Hash值是 CA(证书签发机构) 把持有者的公钥、用途、颁发者、有效时间等信息打成一个包,然后对这些信息进行 Hash 计算得出的。

第二个hash值是CA 使用自己的私钥将该值加密,生成 Certificate Signature,也就是 CA 对证书做了签名。

拿到两个值,客户端就需要使用同样的 Hash 算法获取该证书的 第一个Hash 值 ,到到一个结果,

然后,浏览器收到证书后可以使用 CA 的公钥解密 Certificate Signature 内容,得到第二个 Hash 值,再得到一个结果。

最后两个结果一对比,没问题则开始第三步。

客户端发个Change Cipher Key Exchange给服务端。

包里面有一个新的随机数。

再发一个包Change Cipher Spec

这个包里面则是会话密钥,会话密钥由三个随机数组成,两个hello包里的,一个刚刚发送的,这里使用的是对称密钥

然后再发一个包Encrypted Handshake Message(Finishd),这个包使用了上面的加密内容,需要密钥才可解开

第四次握手

收到了上面的三个包,拆开第一个包获得随机数,然后自己加密一下。

然后Change Cipher Spec,也发Encrypted Handshake Message。

最后双方自行验证,没有问题,连接就建立了。使用会话密钥进行通话。

正则表达式

正则表达式(regular expression)是一种表达文本模式(即字符串结构)的方法,有点像字符串的模板,常常用来按照“给定模式”匹配文本

这里使用js代码来掩饰。

js正则一般表示

ler a = /abc/;  --方法一

let b = new RegExp('abc') -- 方法二

匹配规则

字面量字符和元字符

符号含义
.(点字符)匹配除了回车、换行、行分隔符和段分隔符以外的字符
^表示字符串的开始位置
$表示字符串的结束位置
|(选择符)用来表示“或”的意思
点字符
/a.b/.test('acb')   //true
/a.b/.test('adb')   //true
/a.b/.test('a-b')   //true
/a.b/.test('a:b')   //true
/a.b/.test('accb')   //false
/a.b/.test('a b')   //true

/XXX/:表示正则表达式,test输出布尔值,判断内部内容是否符合。

由上面可知,点字符的匹配只能匹配一次

位置符
/^a/.test('acb')   //true
/ab$/.test('acb')   //false
/^ab$/.test('acb')   //false
/^acb$/.test('acb')   //true
/^acb$/.test('acb acb')   //false

^:表示以什么字符开头,$:则表示以什么字符结尾。两者同时使用则是获取单词,但匹配是整段内容,所以需要注意。

选择符
/a|b/.test('b')   //true
/(a|b)c/.test('ac')   //true
/acd|bcc/.test('acd')   //true

|:表示或,这里的或不仅仅是单个单词也可以是一段字符,即将“|”两端看作整体,以此来取。

特殊字符

  • \cX 表示Ctrl-[X],其中的X是A-Z之中任一个英文字母,用来匹配控制字符。

  • [\b] 匹配退格键(U+0008),不要与\b混淆。

  • \n 匹配换行键。

  • \r 匹配回车键。

  • \t 匹配制表符 tab(U+0009)。

  • \v 匹配垂直制表符(U+000B)。

  • \f 匹配换页符(U+000C)。

  • \0 匹配null字符(U+0000)。

  • \xhh 匹配一个以两位十六进制数(\x00-\xFF)表示的字符。

  • \uhhhh 匹配一个以四位十六进制数(\u0000-\uFFFF)表示的 Unicode 字符。

预定义模式

符号含义
\d匹配0-9的任意数字
\D匹配除了数字的字符
\s匹配空格,即不显示内容的符号,像制表符、换行符
\S匹配除了空格以外的字符
\w匹配任意数字、字母和下划线
\W匹配除了数字、字母和下划线的字符
\b匹配单词边界
\B

匹配非单词边界

小写和大写可以说互为补集,小写不包含的大写包含,反之亦然

/\d*/.test('123')        //true
/\d*/.test('123a')        //false
/\d*/.test('123_')        //false

/\D*/.test('123')        //false
/\D*/.test('abc')        //true
/\D*/.test('\n\r')        //true

/\s*/.test('\n\r\v\f')        //true
/\s*/.test('123')        //false
/\S*/.test('123')        //true

/\w*/.test('123')        //true
/\w*/.test('123abc')        //true
/\w*/.test('1a2b3c_')        //true

/\W*/.test(' :')        //true
/\W*/.test('123:abc')        //false

/\bab/.test('ab cd')        //true
/\bcd/.test('ab cd')        //true
/\bab/.test('ab-cd')        //true
/\bab/.test('abcd')        //false
/\Dab/.test('abcd')        //true

根据上面的大写和小写的特性,可得:\s\S,\d\D,\b\B,\w\W,这四组任何一组均可表示所有字符

量词符

符号含义
表示匹配0次或者是1次
*表示匹配0次或者无数次
+表示匹配一次或者无数次
{}表示范围,视真实情况而定,第一个数字表示至少,第二个是指至多
/a*b/.test('ab')        //true
/a*b/.test('b')        //true
/a*b/.test('aaaaab')        //true

/a+b/.test('ab')        //true
/a+b/.test('b')        //false
/a+b/.test('aaab')        //true

/a?b/.test('ab')        //true
/a?b/.test('b')        //true

/a{1,3}b/.test('ab')        //true
/a{2}b/.test('ab')        //false
/a{,2}b/.test('ab')        //true
/a{3,8}b/.test('aaaaab')        //true

量词符比较常用

括号字符

{}:表示上一个符号出现范围,第一个数字表示至少,第二个数字表示至多。

():表示一个组,将里面内容看作整体

[]:也像选择符一样,里面的字母为“或”关系,但如果在里面加入了^表示非,-表示一定范围

/lo{3,5}k/.test('loook')     //true

'hello world'.replace(/(\w+)\s(\w+)/, '$2 $1')
// "world hello"
这里的()有了标号,1表示第一个内容,2表示后面的内容
第一个()选取的是hello,第二个是word,replace将它们进行了调换

/[abc]/.test('kjhgfds')    //false
/[abc]/.test('kajhgfds')    //true
/[^abc]/.test('qwerty')     //true
/[a-z]/.test('v')    //true
/[A-Z]/.test('a')    //false
/[0-9]/.test('2')    //true
/[0-9a-zA-Z]/.test('asdfgh245')  //true

[]的里面如果使用连字符-则表示一个范围,但这个范围是根据ASCII码来的,需要注意范围。^在里面起到去反作用,这里是需要保留空位的,需要注意。

贪婪匹配

贪婪匹配是针对量词的,像*一旦匹配到前方的内容,使用最多匹配原则,将合适的全部匹配出来。

'abbbbb'.match(/ab*/)      //["abbbbb"]
'abbbbb'.match(/ab+/)      //["abbbbb"]
'abbbbb'.match(/ab?/)      //["ab"]

抑制贪婪匹配则在量词符后添加一个?

'abbbbb'.match(/ab*?/)      //["a"]
'abbbbb'.match(/ab+?/)      //["ab"]
'abbbbb'.match(/ab??/)      //["a"]

修饰符

·i:无视字母大小写

·g:全局匹配

·m:多行匹配

断言

断言有先行断言和先行否定断言之分

先行断言:x(?=y)x只有在y前面才匹配,y不会被计入返回结果。

先行否定断言:x(?!y)x只有不在y前面才匹配,y不会被计入返回结果。

var m = 'abc'.match(/b(?=c)/);   --匹配在c前面的内容
m // ["b"]




/\d+(?!\.)/.exec('3.14')  --不匹配.前面的数字
// ["14"]

this关键字

this指向的几种情况

this都有一个共同点:它总是返回一个对象。

在js中this的指向非常重要。

var person = {
  name: '张三',
  describe: function () {
    return '姓名:'+ this.name;
  }
};

person.describe()
// "姓名:张三"

这里的describe是对象person的一个方法,this.name表示name属性所在的那个对象。由于this.name是在describe方法中调用,而describe方法所在的当前对象是person,因此this指向personthis.name就是person.name

这种的调用比较容易理解,调用对象自身的方法,this的指向依然是对象本身。

var A = {
  name: '张三',
  describe: function () {
    return '姓名:'+ this.name;
  }
};

var B = {
  name: '李四'
};

B.describe = A.describe;
B.describe()
// "姓名:李四"

和上面略有不同,同样是this,但是因为赋值语句的出现,B.describe = A.describe;A的describe方法赋值给了B的方法,所以调用之后就和上面相同,输出对象B的name。

下面这种情况则不相同

var A = {
  name: '张三',
  describe: function () {
    return '姓名:'+ this.name;
  }
};

var name = '李四';
var f = A.describe;
f() // "姓名:李四"

上面内容大同小异,但是赋值是将方法进行了赋值,赋值给了一个变量,但后调用方法,即调用了匿名函数,匿名函数的运行是在全局对象下的,所以此时的this指向全局对象window,window下也存在变量name,所以输出了全局的name。这种情况,将相当于在全局下写了一个匿名函数,然后直接调用的结果。

var f = function () {
  console.log(this.x);
}

var x = 1;
var obj = {
  f: f,
  x: 2,
};

// 单独执行
f() // 1

// obj 环境执行
obj.f() // 2

第一个调用,是调用在全局之下的函数,this的指向是全局,即变量x的值,第二个调用,则是在对象obj下的方法的调用,this指向也就是obj。

所以,在全局下调用全局函数,this的指向就是全局window,但是如果是在全局调用对象的方法,this指向就是对象。但如果在构造函数中,this则指向实例对象。

var Obj = function (p) {
  this.p = p;
};

但一下几种情况会影响this指向

// 情况一
(obj.foo = obj.foo)() // window
// 情况二
(false || obj.foo)() // window
// 情况三
(1, obj.foo)() // window

这里使用的都是立即执行函数。

第一种情况:赋值调用,将方法赋值给了另一个,并直接调用,此时指向window

第二种情况:此时前面为false,执行后面,后面虽然是方法,但是因为立即执行函数,相当于在全局下执行了函数,执行全局

第三种情况:和上面相似,属于直接在全局调用方法,指向window

var a = {
  p: 'Hello',
  b: {
    m: function() {
      console.log(this.p);
    }
  }
};

a.b.m() // undefined

这里是嵌套,对象a里面嵌套了另一个,此时的this指向的应该是a.b,即和方法m同一层的p但是没有所以输出undefined。

this的多层指向

var o = {
  f1: function () {
    console.log(this);
    var f2 = function () {
      console.log(this);
    }();
  }
}

o.f1()
// Object
// Window

this

this的指向不明确,所以,应该避免多层

var o = {
  f1: function () {
    console.log(this);
    var f2 = function () {
      console.log(this);
    }();
  }
}

o.f1()
// Object
// Window

首先是第一个this,属于对象0里面的方法,随意this就指向对象,但第二个给this在函数嵌套里面,不在指向对象,而是指向全局对象。

解决方案

1、that

var o = {
  f1: function() {
    console.log(this);
    var that = this;
    var f2 = function() {
      console.log(that);
    }();
  }
}

o.f1()
// Object
// Object

这里呢就是将第一个this的指向赋值给了一个变量that,that保存着this的指向,即使里面再嵌套that依然不变。

2、严格模式,相当于监控,如果this指向全局就会报错。

var counter = {
  count: 0
};
counter.inc = function () {
  'use strict';
  this.count++
};
var f = counter.inc;
f()
// TypeError: Cannot read property 'count' of undefined

这种,与其说是解决方案,不如说是一种预警,提示编程人员this指飞了。

绑定this

call

var obj = {};

var f = function () {
  return this;
};

f() === window // true
f.call(obj) === obj // true

分明显全局调用,this就指向全局,但是call指定this的指向是obj,所以指向改变。

call还有一个特点:

call方法的参数,应该是一个对象。如果参数为空、nullundefined,则默认传入全局对象。

var n = 123;
var obj = { n: 456 };

function a() {
  console.log(this.n);
}

a.call() // 123
a.call(null) // 123
a.call(undefined) // 123
a.call(window) // 123
a.call(obj) // 456

apply

apply和call相似,call如果传参只能传两个,而apply可以传多个

var obj = {};

var f = function () {
  return this;
};

f() === window // true
f.apply(obj) === obj // true

bind

var counter = {
  count: 0,
  inc: function () {
    this.count++;
  }
};

var func = counter.inc.bind(counter);
func();
counter.count // 1

counter.inc()方法被赋值给变量func。这时必须用bind()方法将inc()内部的this,绑定到counter,否则就会出错。

var counter = {
  count: 0,
  inc: function () {
    this.count++;
  }
};

var obj = {
  count: 100
};
var func = counter.inc.bind(obj);
func();
obj.count // 101

这里是将它,绑在其他的对象,也是可以的。

箭头函数中的this

箭头函数在普通对象中

var code = 404;
let obj = {
    code: 200,
    getCode: () => {
    	console.log(this.code);
    }
}
obj.getCode(); // 404

箭头函数是在定义函数时,就已经指明了this,而不是在调用时。此时的箭头函数指向外面的全局作用域,而不是对象。

箭头函数在函数中

var code = 404;
function F() {
    this.code = 200;
    let getCode = () => {
    	console.log(this.code);
    };
    getCode();
}
var f = new F() //200
var f = F() //构造函数没有new调用,就成为了一个普通函数
console.log(f)
console.log(code)

第一个调用,已经明确指明在对象中了,而第二个构造函数,和前面的普通函数无异。

箭头函数在类中

var code = 404;
class Status {
    constructor(code) {
    	this.code = code;
    }

    getCode = () => {
    	console.log(this.code);
    };
}
let status = new Status(200);
status.getCode(); // 200

同样的已经指明了类,this的指向就是这个类。

let本身就是一个块级作用域,this已经被限定了

综上:this的注意点

  1. this始终指向调用该函数的对象;

  2. 若没有指明调用的对象,则顺着作用域链向上查找,最顶层为global(window)对象;

  3. 箭头函数中的this是定义函数时绑定的,与执行上下文有关

  4. 简单对象(非函数、非类)没有执行上下文;

  5. 类中的this,始终指向该实例对象;

  6. 箭头函数体内的this对象,就是定义该函数时所在的作用域指向的对象,而不是使用时所在的作用域指向的对象。

js的同步和异步

js的执行顺序

js 是一种单线程语言,简单的说就是:只有一条通道,那么在任务多的情况下,就会出现拥挤的情况,这种情况下就产生了 ‘多线程’ ,但是这种“多线程”是通过单线程模仿的,也就是假的。那么就产生了同步任务和异步任务。

所以js为了提高效率,首先会将任务进行分类,分为同步和异步任务。除此自外,异步任务还进行了细分:宏任务和微任务。

宏任务:script、setTimeout、setInterval、postMessage

微任务:Promise.then ES6

所以js是先执行同步任务,同步执行完再执行异步任务,在异步任务中又是先执行微任务再执行宏任务。

案例

setTimeout(function(){
    console.log(1);
});

new Promise(function(resolve){		    
    console.log(2);
    resolve();
}).then(function(){		    
    console.log(3);
}).then(function(){
    console.log(4)
}); 	

console.log(5);
// 2 5 3 4 1

自上而下执行,setTimeout宏任务队列,new Promise同步任务,promise.then微任务队列,console.log同步任务队列。

按照先同步再异步,所以先是Promise,输出2,再console.log输出5.然后异步,先微任务,promise.then,输出3,4,最后宏任务输出1.

function doFoo(fn) {
    this.code = 404;
    fn();
}

function f() {
    setTimeout(() => {
        console.log(">>>" + this); // >>>[object window],语句2
        this.code = 401; 
    }, 0)
    console.log( this.code ); // 404,语句1
}

let obj = {
    code: 200,
    foo: f
};

var code = 500;

doFoo( obj.foo ); 
setTimeout(()=>{console.log(obj.code)}, 0); // 200,语句3
setTimeout(()=>{console.log(window.code)}, 0); // 401,语句4

和上面一样,先是对语句进行划分,先同步,函数中的console.log进行打印,此时的this指向的是f()的上一层,也就是输出404,没有微任务,宏任务顺序执行,第一个计数器输出,这里的this指向计时器的上一层,也就是全局,同时计时器修改了全局里面的this.code值,然后后面两个计时器依次执行,输出obj和window的code值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/800797.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VScode远程不用再输入密码操作

安装插件remote development 1.先检查自己电脑上有没有生成一对公钥和私钥。(一般会在这个目录) 如果没有的话就自己生成一下。 打开命令行输入以下命令 ssh-keygen -t rsa2.在虚拟机中先看一下有没有公钥和私钥。如果没有的话就自己生成一下。 打开…

pytorch2.x 官方quickstart测试

文章目录 1.本地环境2.[安装pytorch](https://pytorch.org/get-started/locally/) (Windows GPU版本)3. [官方quickstart](https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html) 1.本地环境 D:\python2023>nvidia-smi Thu Jul 27 23:27:45…

idea项目依赖全部找不到

目录 1,出错现象2,解决3,其他尝试 1,出错现象 很久没打开的Java项目,打开之后大部分依赖都找不到,出现了所有的含有import语句的文件都会报错和一些注解报红报错,但pom文件中改依赖是确实被引入…

VS2015配置opencv4.1(x86和x64)

1.安装VS2015 vs版本和部门统一,安装C模块即可 2.安装opencv4.1 重点还是配置,安装opencv4.1,装就完事了 3.配置opencv4.1 给整麻了,配了一早上 3.1 在电脑属性中找到“高级系统配置” 3.2 环境变量 3.3 写上x86 和 x64的环…

草稿#systemverilog# 说说Systemverilog中《static》那些事儿(拓展篇)

3)static和automatic可以将一个任务task或者函数function显式地声明成静态或者自动的:一个自动automatic 声明的任务、函数或块内声明的数据缺省情况下具有调用期或激活期内的生命周期,并且具有本地的作用范围; 一个静态static 声…

Java虚拟机——线程与协程

1 Java与线程 目前线程是Java里面进行处理器资源调度的最基本单位。如果日后Loom项目能够为Java引入纤程(Fiber)的话,可能会改变这一点。 1.1 线程的实现 这里先把Java技术的背景放下,以一个通用的应用程序的角度来看线程是如何实现的。 1.1.1 内核线…

C数据结构与算法——顺序查找和二分查找算法 应用

实验任务 (1) 掌握顺序查找算法的实现; (2) 掌握二分查找算法的实现; (3) 掌握两种查找算法的时间复杂度与适用场合。 实验内容 (1) 基于顺序查找表实现顺序查找和二分查找算法; (2) 使用两个不同大小的查找表进行两次理论和实际性能对比&…

利用STM32为主控以LORA为通讯模块,通过中继器链接MQTT服务器的物联网信息采集处理的信息系统方案

项目的详细方案如下: 硬件组成: STM32主控板:作为项目的主控单元,负责采集终端点位的温湿度信息,并通过LORA通讯模块发送数据到中继器。 LORA通讯模块:作为STM32与中继器之间的无线通信模块,负…

【NLP】语音识别 — GMM, HMM

一、说明 在语音识别的深度学习(DL)时代之前,HMM和GMM是语音识别的两项必学技术。现在,有将HMM与深度学习相结合的混合系统,并且有些系统是免费的HMM。我们现在有更多的设计选择。然而,对于许多生成模型来说…

浅谈集成式电力电容器无功补偿装置的技术特点及应用状况

安科瑞 华楠 摘要:阐述了集成式电力电容器无功补偿装置的组成与应用状况.在与常规电力电容器对比的基础上,分析了集成式电力电容器无功补偿装置的技术特点。通过对集成式无功补偿装置原理结构的分析,探讨了对集成式无功补偿装置的…

Spring Batch教程(四)tasklet使用示例:spring batch的定时任务使用

Spring batch 系列文章 Spring Batch教程(一) 简单的介绍以及通过springbatch将xml文件转成txt文件 Spring Batch教程(二)示例:将txt文件转成xml文件以及读取xml文件内容存储到数据库mysql Spring Batch教程&#xff…

TPU-MLIR编译部署算法

注意: 由于SOPHGO SE5微服务器的CPU是基于ARM架构,以下步骤将在基于x86架构CPU的开发环境中完成 初始化开发环境(基于x86架构CPU的开发环境中完成)模型转换 (基于x86架构CPU的开发环境中完成) 处理后的PP-OCR项目文件将被拷贝至 SE5微服务器 上进行推理…

el-table-column 合并列,切换表格显示,数据错乱问题

由于同一个页面需要通过lable进行切换显示不同的表格结果在切换的时候发现表格列错乱了 正常是这样的 切换错乱的是这样的 序号没有了,已接单协同总数列也不见了 切换回来发现第一个表格 原先的两列被后面的挤压了 代码也没啥毛病,最主要的原因是因为同…

【从零开始学习JAVA | 第三十二篇】 异常(下)新手必学!

目录 前言: Exceptions(异常): 异常的两大作用: 异常的处理方式: 1.JVM默认处理 2.自己捕获异常 3.抛出处理 自定义异常: 异常的优点: 总结: 前言: 前…

LUMEN技术要点总结

LUMEN总结 主题是动态全局光照和Lumen Lumen更像是一个各种GI算法的集大成者。 1. 如何理解lumen及全局光照的实现机制 渲染方程 至今为止所有的实时光照都是按照Render Equation来进行渲染的,我们做得到只是在无限的逼近它。 我们把只进行一次反弹叫做SingleBou…

uni-app 经验分享,从入门到离职(一)——初始 uni-app,快速上手(文末送书福利1.0)

文章目录 📋前言🎯什么是 uni-app🎯创建第一个 uni-app 项目🧩前期工作🧩创建项目(熟悉默认项目、结构)🧩运行项目 📝最后🎯文末送书🔥参与方式 &…

客户方数据库服务器CPU负载高优化案例

客户方数据库服务器CPU负载高优化案例 背景 上周线上服务出现一个问题,打开某个页面,会导致其它接口请求响应超时,排查后发现数据库响应超400s,之前1s就可查到数据。 具体原因是有个大屏统计页面,会实时查看各业务服…

echarts坐标轴名称换行

一、期望效果: 期望超过6个字换行,最多可显示十个字 如图: 二、踩坑: echarts的width和overflow设置后换行无效。(如果其他人有设置有效的 还请说明下) 三、解决方案: 用\n换行&#xf…

Django + Xadmin 数据列表复选框显示为空,怎么修复这个问题?

问题描述: 解决方法: 后续发现的报错: 解决方案: 先根据报错信息定位到源代码: 在该文件顶部写入: from django.core import exceptions然后把: except models.FieldDoesNotExist修改为&…

qt6.5 download for kali/ubuntu ,windows (以及配置选项选择)

download and sign in qt官网 sign in onlion Install 1 2 3 4 5