内存图和 JS 世界
JS 小知识:
操作系统常识
一切都运行在内存里
开机
- 操作系统在 C 盘里(macOS 的在根目录下多个目录里)
- 当你按下开机键,主板通电,开始读取固件
- 固件就是固定在主板上的存储设备,里面有开机程序
- 开机程序会将文件里的操作系统加载到内存中运行
操作系统(以 Linux 为例)
- 首先加载操作系统内核
- 然后启动初始化进程,编号为 1,每个进程都有编号
- 启动系统服务: 文件、安全、联网
- 等待用户登录: 输入密码登录/ssh 登录
- 登录后,运行 shell,用户就可以和操作系统对话了
- bash 是一种 shell,图形化界面可认为是一种 shell
打开浏览器
chrome.exe
- 你双击 Chrome 图标,就会运行 chrome.exe 文件
- 开启 Chrome 进程,作为主进程
- 主进程会开启一些辅助进程,如网络服务、GPU 加速
- 你每新建一个网页,就有可能会开启一个子进程
浏览器的功能
-
发起请求,下载 HTML,解析 HTML,下载 CSS,解析 CSS,渲染界面,下载 JS,解析 JS,执行 JS 等
-
功能模块: 用户界面,渲染引擎、JS 引擎、存储等
-
上面的功能模块一般各处于不同的线程(比进程小)
-
如果进程是车间,那么线程就是车间里的流水线
JS 引擎
JS 引擎举例
- Chrome 用的是 V8 引擎, C++编写
- 网景用的是 SpiderMonkey, 后被 Firefox 使用, C++
- Safari 用的是 JavaScriptCore
- IE 用的是 Chakra(JScript9)
- Edge 用的是 Chakra(JavaScript)
- Node.js 用的是 V8 引擎
主要功能
- 编译: 把 JS 代码翻译为机器能执行的字节码或机器码
- 优化: 改写代码,使其更高效
- 执行: 执行上面的字节码或者机器码
- 垃圾回收: 把 JS 用完的内存回收,方便之后再次使用
内存图
瓜分内存
红色区域
作用
- 红色专门用来存放数据,我们目前只研究该区域
- 红色区域并不存变量名
- 每种浏览器的分配规则并不一样
- 上图的区域并不完整,还没有画调用栈、任务队列等区域
Stack 和 Heap
- 红色区域分为 Stack 栈和 Heap 堆
- Stack 区特点: 每个数据顺序存放
- Heap 区特点: 每个数据随机存放
Stack 和 Heap 举例
举例
var a = 1
var b = a
var person = {name: 'frank’, child: {name: ‘jack’}}
var person2 = person
画出内存图如下:
规律
- 数据分两种: 非对象和对象
- 非对象都存在 Stack
- 对象都存在 Heap
数组和函数都是对象
- =号总是会把右边的东西复制到左边
JS 开发者说要有 window
就有了 window(浏览器提供)
还要什么
要有 console
- 于是就有了 console,并且挂到 window 上
要有 document
- 于是就有了 document,并且挂到 window 上
要有对象
- 于是就有了 Object,并且挂到 window 上
- var person = {} 等价于 var person = new Object()
要有数组(一种特殊的对象)
- 于是就有了 Array,并且挂到 window 上
- var a = [1, 2, 3]等价于 var a = new Array(1, 2, 3)
要有函数(一种特殊的对象)
- 于是就有了 Function, 并且挂到 window 上
- funciton f(){} 等价于 var f = new Function()
怎么什么都挂载 window 上?
因为方便,挂在 window 上的东西可以再任何地方直接用
把 window 用内存图画出来
更简单的画法
一般来说,第一个字母大写会有 prototype 属性。
细节
关于 window
- window 变量和 window 对象是两个东西
- window 变量是一个容器,存放 window 对象的地址
- window 对象是 Heap 里的一坨数据
不信的话,可以让 var x = window,那么这个 x 就只想了 window 对象,window 变量就 🈚️ 了。但是这样的代码用弄晕新手,所以不要这样写。
同理
- console 和 console 对象不是同一个东西
- Object 和 Object 对象不是同一个东西
- 前者是内存地址,后者是一坨内存
原型链
思考: 图里的 prototype 是干什么用的
XXX.prototype 存储了 XXX 对象的共同属性,这就是原型。
Q: 这个隐藏属性叫什么?
A:
__proto__
Q:
prototype
和__proto__
区别是什么?A: 都存着原型的地址。只不过
prototype
挂在函数上,__proto__
挂在每个新生成的对象上