JS执行顺序❤️

Posted 学习React

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS执行顺序❤️相关的知识,希望对你有一定的参考价值。


title: JS执行顺序
order: 1


一.概念

1.解释型语言执行步骤

预编译

扫描上下文。扫描错误

函数和变量声明的提升

解释执行

一条一条执行代码

2.任务队列event queue

📢异步任务进入event queue任务队列

所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

具体来说,异步执行的运行机制如下。(同步执行也是如此,因为它可以被视为没有异步任务的异步执行。)

任务进入执行栈----同步任务还是异步任务----同步的进入主线程,异步的进入Event Table并注册函数。当指定的事情>完成时,Event Table会将这个函数移入Event Queue。主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。上述过程会不断重复,也就是常说的Event Loop(事件循环)

📢只要主线程空了,就会去读取"任务队列",这就是javascript的运行机制。这个过程会不断重复。

📢异步任务先进入event table,有结果后进去event queue注册事件,同步任务在主线程执行完后执行事件队列的事件

3.🧡Event Loop

主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。

4.宏任务、微任务的执行顺序

常见的宏任务:setTimeout, setInterval, setImmediate
常见的微任务:Promise.then

执行顺序:先执行同步代码,遇到异步宏任务则将异步宏任务放入宏任务队列中,遇到异步微任务则将异步微任务放入微任务队列中,当所有同步代码执行完毕后,再将异步微任务从队列中调入主线程执行,微任务执行完毕后再将异步宏任务从队列中调入主线程执行,一直循环直至所有任务执行完毕。

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

5.变量提升

匿名函数声明比变量函数声明提身更高

var foo = function () {
    console.log('2');
}
function foo() {
    console.log('1');
}
foo();//2

5.作用域的深层次理解

当函数代码执行的前期 会创建一个执行期上下文内部对象 AO (作用域)

这个内部的对象是预编译的时候创建出来的 因为当函数被调用的时候 会先进行预编译

在全局代码执行的前期会创建一个执行期的上下文的对象 GO

函数作用域预编译

  1. 创建ao对象 AO{}

  2. 找形参和变量声明 将变量和形参名 当作 AO对象的属性名 值为undefined

  3. 实参形参相统一

  4. 在函数体里面找函数声明 值赋予函数体

全局作用域的预编译

  1. 创建GO对象
  2. 找变量声明 将变量名作为GO对象的属性名 值为undefined
  3. 找函数声明 值赋予函数体

6.堆(heap)和栈(stack)

栈会自动分配内存空间,会自动释放。堆动态分配的内层,大小不定也不会自动释放

7.内层的强引用和弱引用

  • 强引用:map就是强引用、引用的那个对象置为null了,map应用的那个地址还存在
  • 弱引用:weakMap就是弱引用、被引用的对象会自动被垃圾回收

二.执行问题

1.考察宏任务微任务

console.log('1');
setTimeout(function(){
    console.log('2');
    new Promise(function(resolve){
        console.log('3');
        resolve();
    }).then(function(){
        console.log('4');
    })
})
new Promise(function(resolve){
    console.log('5');
    resolve();
}).then(function(){
    console.log('6');
})
setTimeout(function(){
    console.log('7');
    new Promise(function(resolve){
        console.log('8');
        resolve();
    }).then(function(){
        console.log('9');
    })
})
//输出1,5,6,2,3,4,7,8,9

2.考察promise

function fun2() {
    console.log(1)
    return Promise.reject('4')//没有catch无法捕获错误,阻止了后面执行
}
async function fun1(){
    console.log(2)
    await fun2()
    console.log(3)
}
fun1()//打印1 2 报错

3.考察闭包

function Foo() {
    var i = 0;
    return function () {
        console.log(i++);
    }
}
var f1 = Foo(),
    f2 = Foo();
f1();//0、闭包延长作用域
f1();//1
f2();//0、匿名函数所以没有指向同一个地址、指向两个不同函数对象

4.考察作用域

(function(){
    //"use strict"在输出b的时候就会Uncaught ReferenceError: a is not defined
    var a=b=5;//相等于var a=5;b=5
})();
console.log(b);//5
console.log(a);//Uncaught ReferenceError: a is not defined

5.考察预编译

function fn(a, c) {
    var a = 123
    console.log(a)//123
    console.log(c)//function c

    function a() {}
    if (false) {
        var d = 678
    }
    console.log(d)//undefined
    console.log(b)//undefined
    var b = function () {}
    console.log(b)///funb

    function c() {}
    console.log(c)//function c
}
fn(1,2)

6.考察函数传参和地址

let obj = {name:'小明'}
function func(a) {
    a.name="小花";
    a={age:18};
}
func(obj);
console.log(obj)

三.定时器经典案例

最简单的一种、没有异步

for(var i=0;i<5;i++){//i++`相当于先赋值后`i+1
	console.log(i)//立即打印了0,1,2,3,4
}

加上定时器、第二个参数可有可无

for (var i = 0; i < 5; ++i) {
    setTimeout(()=>{
        console.log(i)//立即打印出5个5
    })
}
// js 运行环境为单线程,setTimeout 注册的函数需要等到线程空闲时才能执行,此时 for 循环已经结束,i 值为 5,又因为循环中 setTimeout 接受的参数函数通过闭包访问变量 i,所以 5 个定时输出都是 5。

将 setTimeout 放在立即执行函数中、不传参数i

for (var i = 0; i < 5; i++) {
    (function () {
        setTimeout(() => {
            console.log(i)//隔了1s立即打印5个5
        }, i*1000)
    })()
}

传参数i

for (var i = 0; i < 5; i++) {
    (function (i) {
        setTimeout(() => {
            console.log(i)//每秒递增打印
        }, i*1000)
    })(i)
}

以上是关于JS执行顺序❤️的主要内容,如果未能解决你的问题,请参考以下文章

❤️一起谈一谈js中的宏任务和微任务!❤️

js判断的执行顺序

JS执行顺序

JSP页面JS和VBS的先后执行顺序。如何让VBS代码在页面加载完成后执行。

js 怎么让方法执行有先后顺序

js 执行顺序