进程和线程,js单线程,js多任务操作,同步代码和异步代码,执行栈
1.浏览器,js , 执行引擎的关系
js:一门计算机语言,提供表达程序逻辑语法和实现基本功能的API;
浏览器:js语言的真实运行环境,又称为js的宿主环境;
js执行引擎:js宿主环境(如浏览器)中的一个功能模块,用于解析并执行js;
关系:
2.进程和线程
2.1进程
当一个应用程序运行时,需要使用内存和cpu资源,这些资源需要向操作系统申请;操作系统以进程的方式来分配这些资源,一个进程就代表一块独立于其他进程的内存空间,一个应用程序要运行,必须至少有一个进程启动,进程的最大特点就是独立,一个进程不能随意访问其他进程的资源,这就保证多个程序在操作系统上运行互不干扰;
2.2线程
可能同时要执行多个任务,每个任务需要在一个线程上运行,线程与线程之间相互独立,但是可以共享应用程序的进程数据
线程与进程最大的区别
1.进程: 进程之间是无法共享数据,不同的进程代表不同的应用,应用之间共享数据是不安全的,一般无法共享数据,;
2.线程: 可以共享数据,线程是应用程序内部的东西,为了把一个程序运行好,可以共享数据;
3.js是单线程的
**js是单线程的:**由于它的执行引擎只有一个线程,并且不会再执行期间开启新的线程;
注意: 浏览器不是单线程的;
单线程应用程序的特点:
1.易于学习和理解:所有代码都是按照顺序从上到下执行的;
2.易于掌控程序:由于代码都是按照顺序执行的,不会出现中断,也没有共享资源的争夺问题,极大降低了开发难度;
3.更加合理的利用计算机资源:创建新的线程和销毁线程都会耗费额外的CPU和内存资源,没有良好的线程设计,将导致程序运行效率底下,而单线程的应用不受这个影响;
多线程小例子(如图):
4.js多任务操作
任何一个程序在执行期间都可能会开启多个任务,如:
1.任务一: 程序在启动时开启一些操作;
2.任务二:开启一个计时器,每隔一段时间去做一件事;
3.任务三:监听按钮是否被点击,当按钮被点击后,去做一件事;
注意: 由于js线程只有一个,因此要通过异步的方式来解决这些任务;
单线程异步和多线程对比:
多线程:
可以看到,多线程看起来很美好,但是共享数据期间很难控制,多线程的方式运行,会导致程序代码在某些时候会有重叠执行的情况出现,如果这些代码凑巧在使用共享数据,将难以控制最终的运行结果;
单线程:
使用异步的方式解决该问题
js执行时js引擎只开启一个线程,任务一开始执行直到结束,执行期间有其他线程(这些线程与执行代码无关,是浏览器内部的线程,如监听和计时线程),通知js线程(当js线程正在处理某件任务,接到通知后会把正在处理的某件任务做完后,再做接收到通知的任务)
5.同步代码和异步代码
**同步代码:**程序启动后,在js执行线程上立即执行的任务代码;
**异步代码:**收到宿主环境(浏览器)的其它线程通知,即将在js执行线程上执行的代码,例如计时器回调函数中的代码,事件中的代码,js中的异步代码往往放到一个函数中,该函数成为异步函数,或者描述为该函数是异步的;
6.执行栈
为了保证js代码有序的执行,js执行引擎使用执行栈来组织js代码
**每当调用一个函数时,都会创建一个执行上下文,**上下文中提供函数执行需要的环境,创建了上下文之后,在执行函数
例如:下面代码执行过程
console.log(1);
function a() {
console.log('a');
b();
}
function b() {
console.log('b');
}
a();
**1.**代码执行前会创建一个执行栈,执行栈里边有一个初始值,全局上下文(为全局代码提供执行环境)
**2.**首先执行console.log(1)
这个是调用console
对象下的log
函数,执行前现在执行栈中创建一个上下文,然后在执行,执行结果输出1 ,执行完之后,该上下文会立即销毁
销毁后,只剩下全局上下文
3.然后接下来调用函数a,首先在执行栈中创建a的执行上下文,然后在继续看,有一个console.log('a')
,执行前创建一个和上边类似的console.log
执行上下文,然后在执行,输出a;
然后console.log
执行栈立即销毁;
销毁后
4. 继续a函数中代码,调用b函数,首先创建一个b的执行上下文,然后看函数b中的代码,执行console.log('b')
之前创建一个**console.log
的执行上下文**,然后执行,执行结果为b,然后立即销毁console.log
的执行上下文,然后看函数b中是否还有其他代码,没有的话,销毁b的执行上下文,然后观看a函数也没有其他代码,销毁a的执行上下文,然后销毁全局上下文执行结束
执行结束后