JS单线程
- 同步程序执行完成之后,执行异步程序
- js是单线程的,一个任务执行完成之后才执行另一个任务
- process.nextTick(()=>{}),再node环境下才能运行,这个是在异步前执行的 同步-nextTick-异步
- setImmediate,这个是再异步之后执行的 同步-nextTick-异步-setImmediate(当前事件循环结束之后执行)
事件循环(event loop)
- js是单线程的
- 异步是要基于回调来实现的
- event Loop就是异步回调的实现原理
- js是先执行同步的代码,再执行异步的代码
- event Loop过程
1、同步的代码,一行一行放在Call Stack执行
2、遇到异步,会先"记录"下,等待时机(定时,网络请求等)(放在web APIs中)
3、时机到了,就移动到Callback Queue
4、如Call Stack为空(即同步代码执行完成)Event Loop开始工作
5、轮询查找Callback Queue,如有则移动到Call Stack执行
6、然后继续轮询查找(永动机一样)
宏任务和微任务
- 宏任务(macroTask): setTimeout, setInterval, DOM事件, AJAX请求
- 微任务(microTask): Promise, async/await
- 微任务 > DOM渲染 > 宏任务
- 结论: 微任务 执行时机比 宏任务 早
- 同步程序-process.nextTick-微任务-DOM渲染-宏任务-setImmendiate
console.log(1) //1 3 5 8 2 6 7 4
async function async1() {
await async2();
console.log(2)//这个相当于then执行的代码
}
async function async2() {
console.log(3)
}
async1()
setTimeout(function(){
console.log(4)
},0)
new Promise(resolve=>{
console.log(5)
resolve()
}).then(function() {
console.log(6)
}).then(function(){
console.log(7)
})
console.log(8)
防抖与节流
- 防抖:用户接触事件过于频繁,只有最后一次事件的操作
int.oninput = debounce(function() { console.log(this.value) }) function debounce(fn,delay) { let t = null; return function(...args) { if(t!=null) { clearTimeout(t) } t = setTimeout(()=>{ fn.apply(this,args) },delay) } } + vue中在watch中写防抖事件不起作用, 在watch中写this.debounceValue(), 在mounted中写this.debounceValue = this.common.debounce(()=>{ this.onLoad() },500)
- 节流: 控制执行的次数 控制高频时间的执行次数
function throttle(fn,delay) {
let t = null;
return function(...args) {
if(t!=null) {
return
}
t = setTimeout(()=>{
fn.apply(this,args)
clearTimeout(t)
},delay)
}
}
回调&&promise&&async/await
- 回调函数解决异步的时候,要不停的嵌套,易出现回调地狱,不易于维护
- promise 解决回调,用.then() 的方法 这个方法会出现链式的then
function getTea() {
return new Promise((resolve) => {
setTimeout(()=>{
resolve("茶")
},500)
})
}
function HuoG() {
return new Promise((resolve) => {
setTimeout(()=>{
resolve("火锅")
},1000)
})
}
getTea().then((res)=>{//如果回调多就会出现一堆的then
console.log(res)
return HuoG()
}).then((res)=> {
console.log(res)
})
// async/await 更清晰 和同步一样
function getTea() {
return new Promise((resolve) => {
setTimeout(()=>{
resolve("茶")
},500)
})
}
function HuoG() {
return new Promise((resolve) => {
setTimeout(()=>{
resolve("火锅")
},1000)
})
}
async function getData() {
//直接获取resolve传递出来的异步数据
let HotPot = await HuoG();//异步数据写出来更像时同步的 拿到数据再往下执行
console.log(HotPot);
let tea = await getTea();
console.log(tea)
}
getData()
// asyc 返回的是一个promise对象
async function fun() {
return 1
}
fun().then((data)=>{
console.log(data)//1
})
闭包
- 函数嵌套函数,内部函数就是闭包
- 闭包,内层函数没有执行完成,外部函数变量不会被销毁
- 可以封装代码,实现模块化
let module = (function(){
let a = 10;
let b = 20;
function add(){
return a + b;
}
function sub() {
return a - b;
}
return {
add,
sub
}
})();
console.log(module.add());
console.log(module.sub());
原型,继承
+ 获取原型的方法
- 1.通过对象的__proto__获取
- 2.通过构造函数的prototype属性拿到原型
- 3.通过类的prototype获取
- 所以的原型最上层都是Object.prototype的原型上
let cat = {
name: "喵喵"
}
cat.__proto__.eat = function() {
console.log("吃鱼")
}
cat.eat();
function User(name,age) {//es5写法 构造函数
this.name = name;
this.age = age;
this.login = function() {
console.log("登录")
}
}
function Amdin() {
this.deletePerson = function() {
console.log("删除一个人")
}
}
Amdin.prototype = new User();//es5的继承
let admin = new Admin("喵喵",2);
admin.login()
admin.deletePerson()
class User1 {//es6写法 类
constructor(name,age) {
this.name = name;
this.age = age;
}
login() {
console.log("登录")
}
}
class Admin1 extends User1{//es6继承
deletePerson() {
console.log("删除一个人")
}
}
let admin1 = new Admin("喵喵",2);
admin1.login()
admin1.deletePerson()
this的指向
+ 方法中的this,指向调用方法的对象
+ 全局环境下指向全局对象
+ 全局函数中的this,指向全局对象
+ 内部函数中的this,指向全局hans
+ 事件中的this,指向触发事件的DOM对象
+ 构造函数中的this,指向new创建的对象 (new会创建函数,将构造函数的this指向创建出来的对象)
+ 箭头函数中的this,指向定义函数上下文的this
call/apply/bind
+ call 函数的一种方法,改变this的方向 并且可以调用函数 主要作用也可以实现继承 dog.eat.call(cat,"鱼","肉")
+ apply 函数的一种方法,改变this的方向 并且可以调用函数 主要应用,比如可以利用apply可以求得数组中最大值 const arr = [1, 22, 3, 44, 5, 66, 7, 88, 9];
const max = Math.max.apply(Math, arr);
console.log(max);
+ bind 函数的一种方法,改变this的方向 不调用函数 let fun = dog.eat.bind(cat,"鱼","肉"); fun() 永久绑定
// this实现继承
function Animal() {
this.eat = function() {
console.log("吃东西")
}
}
function Fly() {
this.fly = function() {
console.log("会飞")
}
}
function Cat(){
Animal.call(this) //call可以实现多重继承
Fly.call(this)
}
let cat = new Cat();
cat.eat()
cat.fly()
深拷贝/浅拷贝
+ 浅拷贝只能拷贝原始类型 引用类型无法进行拷贝 for...in
+ 深拷贝 使用递归的方法进行
```js
function copy(obj) {
let newObj = {};
for(let i in obj) {
if(obj[i] instanceof Object) {
newObj[i] = copy(obj[i])
}else {
newObj[i] = obj[i]
}
}
return newObj
}
// 深拷贝 使用JSON.strigify和JSON.parse
- function copy(obj) {
let str = JSON.stringify(obj);
let newObj = JSON.parse(str);
return newObj
}
标签:function,异步,console,log,任务,let,return,EVENT,LOOP
From: https://www.cnblogs.com/dd22blogs/p/16737898.html