程序&进程&线程
程序
程序是一个静态的实体,储存在磁盘里。(本质上是某个数据的集合)比如我写完一串C语言代码,编译完成后会生成一个.exe文件,这就是储存在磁盘中的一个程序。
进程
进程是一个动态的实体,是程序的执行,加载在内存中。比如我点开一个.exe程序,它就会在内存里加载出一个进程。多个进程之间是并发的关系而不是并行的关系。进程之间不共享内存,使之交互变得困难,同时多个进程以及子进程会导致内存的浪费。
线程
线程是CPU的最小执行单位,一个进程可以有多个线程。同一进程下多个线程之间也是并发关系且共享内存,极大地提高了程序的运行效率
浏览器架构和事件循环
现代浏览器架构
多进程:主进程负责浏览器界面,用户交互,管理子进程,提供储存功能等,此外还有插件进程,网络进程,GPU进程,渲染进程(内核)等
事件循环的作用
让渲染引擎与JS引擎相互配合,确保JavaScript单线程的同时防止HTML解析与页面渲染的堵塞
异步以及它的实现
- 异步是指不在主线程执行,而是通过任务队列通知主线程,达成不等任务执行完,直接执行下一个任务。
- 将一个耗时长的任务(定时器,网络请求,用户交互等)从主线程里剔出放入任务队列里,等待主线程任务完成后进行事件循环再将该任务拿回来执行
变量
一个进程可以大致分为两大部分,代码段(text)和数据段(stack(栈)+heap(堆)+data(JS没有data段))。
栈(stack)的特点:
- 结构性强,内存连续
- 寻址速度快
- 数据稳定(每一个数据的大小都是确定的(IEE754(64位))
- 容量小
栈里面存的东西有两种,一种是基本数据类型,另一种是引用数据类型的标识符(因为程序只允许访问栈而不能访问堆,(没有访问堆的权限)所以要通过栈通过标识符来间接的访问堆)
堆(heap)的特点:
- 类似于书架(里面存储的数据可以直接的随意的查取)
- 存储以堆为单位的数据
- 容量大(堆和栈的容量大小总量一定,通常会把堆的容量设计得大一些)
- 不同数据间内存不连续
JS中的变量类型
-
原始类型(primitive type):
基本数据类型(原始类型)一般存在栈里。基本数据不可修改(基本类型存在栈里,每次会增加一个新的内存而不能直接改动原来的数据)
-
引用类型(reference type):
JS里的引用类型就是对象,对象存在堆里。(存在堆里的原因:对象大小不确定,它可能会拥有很多很多的属性、数据)
对象是JS中唯一可变的值。(函数也是对象)
var r1 = { a: 1, }, r2 = r1; r2.a = 2; console.log(r1.a, r2.a);以上代码实现方式:先在栈里面压入了一个变量被标记为r1,它存的值是后面的对象在堆内存的地址。然后
r2 = r1则是把r1的地址赋给了r2(因为只能访问栈),所以r1和r2都指向了堆里面的a,现在r2.a = 2则是直接把a的值进行了修改,所以r1与r2的值均发生改变。
关于字符串:根据ECMA规定,字符串是基本类型,存在栈里,但实际上的使用需要用到堆,比如下面这串代码:
var a = 'hello world';
b = a;
b = 'hello';
console.log(a,b);
值传递和引用传递
例:
function change1(arg){
arg = 200;
}
function change2(arg){
arg.a = 200;
}
var foo = 100;
var bar = { a: 100 };
change1(foo);
change2(bar);
console.log(bar.a);
console.log(foo, bar);
打印结果为:
100
200