(1)所有同步任务在主线程上执行,形成一个执行栈
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务(setInterval,setTimeout,i/o...)有了结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",拿到队列的第一个任务,进入执行栈,开始执行。
(4)主线程不断重复上面的(3)。
主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)
Promise的出现让问题变复杂了, 它跟setTimeout 优先级? 上面的事件循环解释不够用了。
console.log('script start')
setTimeout(function() {
console.log('timer over')
}, 0)
Promise.resolve().then(function() {
console.log('promise1')
}).then(function() {
console.log('promise2')
})
console.log('script end')
// script start
// script end
// promise1
// promise2
// timer over
所有任务分为宏任务(macrotask )和微任务(microtask ) 两种。
MacroTask(宏任务):* script全部代码、setTimeout、setInterval、I/O、UI Rendering。
MicroTask(微任务):* Process.nextTick(Node独有)、Promise...
在挂起任务时,JS 引擎会将所有任务按照类别分到这两个队列中,首先在 宏任务 的队列中取出第一个任务,执行完毕后取出 微任务 队列中的所有任务顺序执行;之后新的事件循环开始,取宏任务的第一个,周而复始,直至两个队列的任务都取完。
http状态码有那些?分别代表是什么意思?
[
100 Continue 继续,一般在发送post请求时,已发送了http header之后服务端将返回此信息,表示确认,之后发送具体参数信息
200 OK 正常返回信息
201 Created 请求成功并且服务器创建了新的资源
202 Accepted 服务器已接受请求,但尚未处理
301 Moved Permanently 请求的网页已永久移动到新位置。
302 Found 临时性重定向。
307 Internal Redirect 内部重定向
304 Not Modified 自从上次请求后,请求的网页未修改过。 协商缓存
200 memory cache 强缓存
400 Bad Request 服务器无法理解请求的格式,客户端不应当尝试再次使用相同的内容发起请求。
401 Unauthorized 请求未授权。
403 Forbidden 禁止访问。
404 Not Found 找不到如何与 URI 相匹配的资源。
500 Internal Server Error 最常见的服务器端错误。
503 Service Unavailable 服务器端暂时无法处理请求(可能是过载或维护)。
]
CSRF
(Cross-site request forgery
):跨站请求伪造。
用户是网站A的注册用户,且登录进去,于是网站A就给用户下发
cookie
。
从上图可以看出,要完成一次
CSRF
攻击,受害者必须满足两个必要的条件:
A
,并在本地生成Cookie
。(如果用户没有登录网站A
,那么网站B
在诱导的时候,请求网站A
的api
接口时,会提示你登录)A
的情况下,访问危险网站B
(其实是利用了网站A
的漏洞)。我们在讲
CSRF
时,一定要把上面的两点说清楚。
温馨提示一下,
cookie
保证了用户可以处于登录状态,但网站B
其实拿不到cookie
。
举个例子,前段时间里,微博网站有个
api
接口有漏洞,导致很多用户的粉丝暴增。
CSRF的防范措施
方法一、Token 验证:(用的最多)
token
;token
。token
不合法,那么服务器拒绝这个请求。方法二:隐藏令牌:
token
隐藏在 http
的 head
头中。方法二和方法一有点像,本质上没有太大区别,只是使用方式上有区别。
方法三、Referer 验证:
Referer
指的是页面请求来源。意思是,只接受本站的请求,服务器才做响应;如果不是,就拦截。
XSS
攻击的核心原理是:不需要你做任何的登录认证,它会通过合法的操作(比如在url
中输入、在评论框中输入),向你的页面注入脚本(可能是js
、hmtl
代码块等)。
最后导致的结果可能是:
Cookie
D-doss
攻击XSS的防范措施主要有三个:
1. 编码:
对用户输入的数据进行
HTML Entity
编码。
2、过滤:
onerror
可以自动触发攻击,还有onclick
等。(总而言是,过滤掉一些不安全的内容)Style
节点、Script
节点、Iframe
节点。(尤其是Script
节点,它可是支持跨域的呀,一定要移除)。面试官还可能喜欢问二者的区别。
CSRF
:是利用网站A
本身的漏洞,去请求网站A
的api
。XSS
:是向网站 A
注入 JS
代码,然后执行 JS
里的代码,篡改网站A
的内容。let和const,解构赋值、模板字符串、箭头函数。
Symbol、Map、Set三种常用的数据类型。
Proxy重新定义了数据劫持的能力
Reflect定义了一套标准化的数据操作的方式
Promise确实的解决了异步逻辑嵌套及回调地狱问题。定义了异步逻辑的三种状态pending、rejected、fullfilled, 搭配then、catch、all、race等方法以及async await语法糖,大量简化了异步操作。
Generator函数,可以将异步逻辑划片执行。
新增了class类的概念
ES6 Modules
ES6新增了定义变量的关键字 let和const, 分别用于定义块级变量和常量
let, const不会声明提前, 存在暂时性死区
外部无法使用到内部的let和const定义的变量, 存在块级作用域限制]
const 定义的常量, 无法更改。
if(true){
let name ="kerwin"
}
const obj = {name:"kerwin"}
obj.name="xiaoming"
// obj = {name:"xioamng"}
// obj= 'dwadwa'
箭头函数是ES6推出的,所以在低版本浏览器是有兼容问题的,语法简介明了,逻辑更清晰。
箭头函数没有自己的this,this指向外部的this,并且this会在创建的时候就绑定好.
const fn1 = function() {
console.log(this)
}
fn1() // window
const obj = {
name: 'tom',
fn2 () {
fn1() // window
console.log(this) // obj
}
}
obj.fn2()
// 在箭头函数定义的位置往上数,这一行是可以打印出 this 的
// 因为这里的 this 是 window
// 所以箭头函数内部的 this 就是 window
const obj = {
fn: function () {
console.log(this)
},
// 这个位置是箭头函数的上一行,但是不能打印出 this
fun: () => {
// 箭头函数内部的 this 是书写箭头函数的上一行一个可以打印出 this 的位置
console.log(this)
}
}
obj.fn()
obj.fun()
let {type,payload} = data; // {type:"",payload:""}
[...arr1,...arr2]
{...obj1,...obj2}
//异步处理方案
1. 回调函数
2. Promise
3. generator 生成器 yield
4. async await
//解决回调地狱 ,嵌套金字塔
function test1(){
return new Promise((resolve,rejet)=>{
setTimeout(() => {
resolve("123")
}, 2000)
})
}
test1().then(res=>{
}).catch(error=>{
})
// pending reject fullfilled
axios.get("1.php").then(res=>{
return axios.get(2.php,{res})
}).then(res=>{
return axios.get(3.php)
}).then(res=>{
console.log(res.data)
}).catch(error=>{
console.log(error)
})
async await 写起来
async function test(){
var a = await axios.get(1);
var b= await axios.get(2,{a});
var c= await axios.get(3,{b})
console.log(c);
}
test()
//所有的异步都结束
Promise.all([axios.get(1),axios.get(2)]).then(res=>{
//loading隐藏
}).catch(error=>{
})
Promise.race([axios.get(1),axios.get(2)])
`Promise.any()`跟`Promise.race()`方法很像,只有一点不同,就是`Promise.any()`不会因为某个 Promise 变成`rejected`状态而结束,必须等到所有参数 Promise 变成`rejected`状态才会结束。
class Person{
constructor(name,age) {
this.name = name;
this.age =age;
}
say=()=>{
}
}
class Test extends person{
constructor(name,age,location) {
super(name,age);
this.location = location;
}
}
import obj from "./a" ;
export default aaa;
import {test} from "./b" ;
export {test} ;
export var test =function(){}
AMD - 前端 异步加载 - 提前下载, 提前加载 require.js
CMD - 异步加载 - 提前下载 , 按需加载 -- 玉伯 -sea.js
CommonJs -同步加载(webpack)
require("./b")
=>module.exports
=>exports
ES6 - 模块化
//ES6 和 commonJS区别?
//ES6可以导入某几个接口 import {a} from './module.js' + webpack- tree shaking 摇树优化
//commonJS 导入整个文件
Generator 函数返回一个同步遍历器,异步 Generator 函数的作用,是返回一个异步遍历器对象。在语法上,异步 Generator 函数就是async函数与 Generator 函数的结合。
function timer(t) {
return new Promise(resolve => {
setTimeout(() => {
resolve(t)
}, t)
})
}
async function* fn() {
yield timer(1000)//任务1
yield timer(2000)//任务2
yield timer(3000)//任务3
}
// 使用一下 for await ...of
async function fn1() {
for await(const val of fn()) {
console.log("start",Date.now())
console.log(val);
console.log("end",Date.now())
}
}
fn1();
async await 存在的问题 for of循环是同步的await 打断内部代码
这部分代码没有明显的语法错误,但存在一个问题:异步操作是并发执行的,但在 test 函数中使用了 for…of 循环,它会阻塞后续代码的执行,导致所有异步操作都是串行执行的,而不是并发执行的。这意味着在执行 arr 中的第一个异步操作时,后续的异步操作会被阻塞,直到第一个异步操作完成后才会执行下一个异步操作。这样会导致程序的执行效率比较低,特别是在处理大量异步操作时,会花费更长的时间。
function timer(t) {
return new Promise(reslove => {
setTimeout(() => {
reslove('data--' + t)
}, t);
})
}
//存在的问题应该是卡住代码块(第一个结束了 执行代码快)
async function test() {
let arr = [timer(1000), timer(2000), timer(3000),]
for (const item of arr) {
console.log("start-" + Date.now());
console.log(await item);
console.log("end-" + Date.now());
}
}
test()
同步生成器不符合promise的链式调用
let arr = [1, 2, 3]
let i = arr[Symbol.iterator]()
console.log(i.next());
console.log(i.next());
console.log(i.next());
console.log(i.next());
for (const i of arr) {
console.log(i);
}
// 生成器函数 会得到遍历器
function* gen() {
yield 11
yield 22
}
let g = gen()
console.log(g.next());
console.log(g.next());
console.log(g.next());
function ajax(data) {
return new Promise(reslove => {
reslove(data)
})
}
function* gen2() {
yield ajax(1)
yield ajax(2)
}
let g2 = gen2()
// console.log(g2.next());
// console.log(g2.next());
// console.log(g2.next());
g2.next().value.then(res => {
console.log(res);
})
g2.next().value.then(res => {
console.log(res);
})
异步生成器
这段代码定义了一个异步生成器函数 gen(),它返回一个异步迭代器。异步迭代器是一种特殊的迭代器,它的 next() 方法返回一个 Promise 对象,可以使用 await 等待 Promise 对象的结果。在 gen() 中,使用 yield 关键字返回两个 Promise 对象。
接下来定义了一个异步函数 test(),它使用 g.next() 方法获取异步迭代器 g 中的下一个 Promise 对象,并将它们存储在一个数组中。然后使用 for await…of 循环遍历数组中的 Promise 对象,等待它们的结果并打印输出。
最后,调用 test() 函数执行异步任务。执行结果会依次输出 1 和 2,表示异步生成器中的两个 Promise 对象的结果。
// 异步生成器
async function* gen() {
yield ajax(1)
yield ajax(2)
}
let g = gen()//得到异步遍历器
// g.next().then(res => {
// console.log(res);
// return g.next()
// }).then(res => {
// console.log(res);
// return g.next()
// }).then(res => {
// console.log(res);
// })
// async function test() {
// let res1 = await g.next()
// console.log(res1);
// let res2 = await g.next()
// console.log(res2);
// let res3 = await g.next()
// console.log(res3);
// }
async function test() {
let list = [g.next(), g.next(), g.next()]
for await (let i of list) {
console.log(i);
}
}