什么是单线程
同一时间只能做一件事情.
其实语言的特性都是和其应用场景相互结合的;
javascript 主要是操作dom,如果多线程,同时去添加和删除dom节点
那不就乱套了么
顺便了解:在网页渲染的时候,js的加载和ui的渲染是共享线程的,是互斥的,不会同时加载,这也是为什么我们说把script放在body上面可能会导致页面发生阻塞(也就是肉眼看到页面会晚).
了解javascript堆栈
看到堆栈,我们就会想到
- 栈是保存变量引用和简单变量的
- 堆是保存对象的
所以函数的引用是在栈中,函数执行的过程其实就是内存的数据操作的过程,所以函数在执行的时候,堆和栈内存是都会有变化.
function changeVal(val){
val=2;
}
function changeObj(obj){
obj.name="changed name"
}
var val = 1;
var obj = {name:"my name"};
changeVal(val);
changeObj(obj)
// 你们觉得下面输出分别是什么呢,自己执行以下
console.log(val);
console.log(obj)
复制代码
通过上面简单说说js的执行阶段
- EC (Execution Context) 执行上下文,也就是执行环境
javascript 解析器解析创建的过程,比如变量声明,变量提升等(只是声明)
例如:上面会构建 ECobj={ variableObject:{ changeVal:Function, changeObj:Function, val:1, obj:Object } } 复制代码
- ECS (执行环境栈)
声明的代码入栈
上面为什么val=1,而obj={name:"changed name"}
因为函数运行时,changeVal只是执行环境中,只是在栈中声明了name然后赋值,执行完就销毁了
而changeObj 传入的是对象的引用,改变的是堆内存中的数据(需要注意的是,在函数中对对象引用的指向修改是无效的)
例如: changeVal(obj)
console.log(obj) => {name:"changed name"};
复制代码
为什么javascript是单线程的,ajax算什么
javascript是单线程的,是由它的执行机制决定的.下面说说过程,是什么机制?
- javasript 代码执行会开启线程,线程的运行是要在内存中运行的,此时,javascript的主线程会开辟自己的堆栈.
- javascript引擎解析后会在执行栈中执行.用代码说话
function a();
setTimeout();
function b();
ajax;
复制代码
入栈过程
1.a 入栈执行
2.setTimeout (浏览器)会开启一个异步任务,会托管给事件计数器去计数
3.b入栈执行
4.ajax (浏览器会开启一个异步网络任务去请求),也会托管给事件计数器计数
这里你会想,不是说javascript是单线程的么,它开启异步任务,不就是开启线程去执行么.(你说的对,这些线程都是浏览器提供的) 但是(下面很重要)
上面的setTimeout 和ajax执行完返回的结果会进行排队,会放在事件队列中,等待执行栈中执行完,也就是主线程执行完毕之后再来一个个的执行.
综上所述:js执行过程是没有在一个时间点同时执行的,是在一个时间点执行一件事,下一件事要执行,不好意思,排队执行.
所以,像你感觉到的setTimeout和ajax异步线程,是浏览器环境提供开启的,针对javascript语言的执行机制来看,它确实是单线程的
1.首先看任务栈
Math sin()
qux() 这里有一些异步操作,浏览器会开启相关线程去操作,下面的baz()会执行
baz()
...
这些除了qux()的事件会先执行完.
2.异步任务根据执行完的先后把结果放在队列中,然后通过event loop 循环去一个个的取. 这个取的前提是在执行栈中事件已经清空,也就是都执行完之后.
通过上面的讲解,大家应该清楚javascript为什么被称为是单线程语言了吧.