一、进程与线程
1.英语小课堂
- Operating System 操作系统,简称OS
- runtime 运行时(运行时你所需要的所有东西)
JS运行的时候需要浏览器,那么浏览器就会提供一个运行时给JS - environment 环境,简称env
- person 一个人
- kernel 内核
- compile 编译
- memory 记忆、存储
- people 一群人(person的复数)
2.操作系统常识
一切都运行在内存里
2.1 开机
通电——读固件——加载开机程序——操作系统被加载到程序里
- 操作系统在C盘里(macOS的在根目录下多个目录里)
- 当你按下开机键,主板通电,开始读取固件
固件:固定在主板里的内存卡,里面写死了主板的程序 - 开机程序就会将文件里的操作系统加载到内存中运行
2.2 操作系统被加载到内存以后做什么?(以Linux为例子)
操作系统的内核叫kernel
提供给用户的操作界面叫shell
- 首先加载操作系统内核
预先加载所有最重要的功能,例如:上网模块、文件管理、操作显示器,操作系统把最基本的功能嵌入了内核,就不用额外打开程序就可以用。 - 然后启动初始化进程,编号为1,每个进程都有编号
进程:一个exe文件双击后就可以启动一个进程
任务管理器——PID
如:某程序PID=1120,表示该程序是在电脑上第1120个打开的程序 - 启动系统服务:文件、安全、联网
- 等待用户登陆:输入密码登陆/ssh登陆
ssh:远程登陆 - 登陆后运行shell,用户就可以和操作系统对话了
Windows系统登陆后就是桌面,而Linux系统登陆后会有一个黑框用来输入命令 - bash是一种shell,图形化界面可认为是一种shell
cmder里面就有bash,bash是一个ba的人写的shell
图形化界面:也就是桌面,可以通过鼠标点击
2.3 打开浏览器
2.3.1 chrome.exe
- 双击Chrome图标,运行Chrome文件
- 双击开启Chrome进行,作为主进程
- 主进程会开启一些辅助进程,如网络服务、GPU加速
- 用户每新建一个网页,就有可能开启一个子进程
2.3.2 浏览器的功能
- 发起请求,下载HTML,解析HTML,下载CSS,解析CSS,渲染界面,下载JS,解析JS,执行JS等
如:浏览器输入baidu.com
1.向百度服务器发起请求,下载对应的HTML,得到一个文本,读取HTML,HTML引用了一个CSS,就去下载CSS解析。
2.渲染:HTML和CSS解析完要合起来,HTML提供节点,CSS提供节点的样式,合起来显示屏幕上
3.HTML引用了JS,下载读取JS,边解析边执行。(执行就是把命令打印到控制台) - 浏览器完成以上功能的模块:用户界面、渲染引擎、JS引擎、存储等
渲染引擎:就是把得到的HTML和CSS合起来,渲染得到一个界面的代码。引擎不是发动机而是一个代码,就是把代码运行起来。(HTML和CSS公用一个引擎是因为HTML是有默认样式的,因此要放在一起)
JS引擎:解析并执行JS(下载是网络模块执行)。
JS是怎么渲染的?
答:线程通信,JS要修改HTML或者CSS,不能直接修改,要通过线程之间的通信来通知渲染引擎,这叫做跨线程通信。(谷歌会提供通信接口)
跨线程通信要比线程馁慢,所以DOM操作慢。 - 上面功能模块一般各处于不同的线程(比进程更小一级的东西)
理解:例如百度打开一个知乎网页,知乎网页这个页面上运行渲染引擎和JS引擎,知乎已经是一个进程了,而这两个引擎在知乎页面内运行,成为线程。
每一个页面都会开启一个渲染线程和JS线程。
JS是单线程的 - 如果进程是车间,那么线程就是车间里的流水线
二、JS引擎
1.JS引擎举例
现在说引擎默认V8
- Chrome用的是V8引擎,C++编写
作者写了8个引擎,第8个是给JS写的。
C++是性能王者 - 网景用的是SpiderMonkey,后被Firefox使用,C++
蜘蛛猴 - Safari用的是JavaScriptCore
- IE用的是Chakra(JScript9)
查克拉,用的查克拉的JS版本 - Edge用的是Chakra(JavaScript)
IE12用的查克拉的JS版本 - Node.js用的是V8引擎
2.JS引擎的主要功能
- 编译:把JS代码翻译为机器能执行的字节码或机器码
机器码是二进制,字节码是二进制再转一次 - 优化:改写代码,使其更高效
- 执行:执行上面的字节码或者机器码
- 垃圾回收:把JS用完的内存回收,方便再次使用
将用完的变量回收,下次再申请变量时再用
3.执行JS代码
在执行代码之前,浏览器需要做什么
1.准备工作
- 提供API:window / document / setTimeout
- 以上都是浏览器提供给JS的功能,不是JS自身具备的功能
- 将这些功能(如window)称为运行环境 runtime env
- 一旦把JS放进页面,就开始执行JS
2.深入研究
- JS代码在哪里运行?
答:内存。一个HTML引用了JS,下载后代码放到内存里。 - 代码放到哪个内存里?
答:下方内存图解释
三、内存图
3.1 瓜分内存
- 当操作系统运行后,所有的东西都会进入8G内存里
- JS引擎瓜分内存:代码区(存代码的)
- 不知道什么区abc:存储变量,存下环境,代码区里面的a存入这个区,数字1存到红色区域
- stack(栈区):数据区的stack
- heap(堆区):数据区的heap
3.2 红色区域
1.作用
- 红色专门用来存放数据,我们目前只研究该区域
- 红色区域并不存变量名,变量名在[不知什么区](绿色区域)
- 每种浏览器的分配规则不一样
- 除了上图标出来的还有:调用栈、任务队列等区域
2.Stack和Heap
- 红色区域氛围Stack栈和Heap堆
- Stack区特点:每个数据顺序存放(不准跳格存放)
- Heap区特点:每个数据随机存放(每次都随机找位置开辟区域存储,要是之前存的内容后面的位置占了,想要扩大时就重新找个位置存,前面的释放掉)
3.3 Stack和Heap举例
1.代码
var a = 1
var b = a
//把a对应的内存里面的数据直接拷贝到b,数值就直接存,对象就拷贝地址
var person = {name:'frank',child:{name:'jack'}}
//只要是个对象都要开辟新空间来存,因此child里面的不能直接存到child那块内存里,把内存的地址发发你感到child中
- a在不知什么区存储,数据1(64位)存储在stack区域中,当 b=a时,把a对应的内存里面的数据直接拷贝到b,纯拷贝
- person(简称p)中的对象存储在heap中的随机区域,其中child中的对象(对象中的对象)另外开辟地址存放(所有的对象都要开辟新空间来存),后续将地址发到child中即可
- p在stack中存储对象的地址即可,p2同理与上面的b
- 当 p2.name=‘x’,p.name=?
答:p2根据#108找到相应对象并修改,而地址不变,因此p对应的对象内容也修改,应该也是x - 为什么p中的对象要存在Heap?
答:如果内容存在Stack时,由于按照顺序存放,person中再加内容(如加一行:p.age=18),p后面已经有占位了,就无法再添加进新的东西,而Heap是随机存放,大多数时候后面都是没有对象的,因此可以添加。
2.规律
- 数据分两种:非对象和对象
- 非对象都存在Stack(数字、字符串、布尔)
- 对象都存在Heap(数组、函数等)
- =号总是会把右边的东西直接左边(不存在什么传值和传址)
3.区分值和地址
会画内存图就不需要区分值和地址
JS世界
JS写第一行代码前的内存长什么样?
1.JS开发者说要有全局对象window,所以浏览器就提供了window
2.还要什么?
- console:挂到window上,window.console
- document:挂到window上,window.document
- object:对象,挂到window上,window.object,其中
var person = {}
等价于var person = new Object()
- array:数组,挂到window上,window.array,其中
var a = [1,2,3]
等价于var a = new Array(1,2,3)
- function:函数,挂到window上,window.function,其中
function f(){}
等价于new Function()
在开始开始写代码之前至少有5个对象都挂到window上
上面的等价式后者是正规写法,但没人用,前者不正规但好用,简写更好用。
3.挂在window上的原因
方便,挂在window上的东西可以在任何地方直接用
把window用内存图画出来。(对象只有地址,没有名字)
更加简化的画法
- 对象是没有名字的:一个对象只有地址,没有名字,如Heap中的对象开辟了一个区域地址为#90
而只是因为其地址Stack存下来了,其中window在不知道什么区,内容在Heap区,它们是通过stack中的地址联系起来而已,所以认为window是它的名字。
因此下图中的对象名不属于这块内容。 - window.console指向/引用了某个对象。(console保存了那个对象的地址)
指向/引用:保存了其地址
总结该图: - window有三个属性,第一个属性指向console;第二个属性Object指向了一个函数,函数有两个属性;Array指向了一个对象,对象也有两个属性(一般第一个字母大写就会有prototype)。
- object是个函数,可以创造一个新的对象,
console.dir(window.object)
,其中dir的意思是打出它的结构
4.细节
4.1 关于window
- window变量和window对象是两个东西(变量是在不知道什么区,对象是在#90号内存),只是恰巧变量保存了对象的地址,变量和对象没什么关系
- window变量是一个容器,存放window对象的地址。(可以存放不同的地址)
- window对象是Heap里面的一坨数据
- 当让
var x = window
,那么x就指向了window对象,那么window变量就可以不要了,如 x.console,但容易弄混,尽量不要这样改。
4.2 同理
- console和console变量不是同一个东西
console是window里面存的一个属性,#90号地址的第一行就是console,而console对象在#28号 - object和object函数对象不是同一个东西
- 前者是内存地址,后者是一坨内存