JS世界

391 阅读4分钟

1.一切都运行在内存里

\quad 是否好奇过,电脑按下开机键到屏幕亮起的这个过程中,发生了什么?我们知道,Windows操作系统在C盘中(macOS在根目录的多个文件夹中),当你按下开机键,主板通电,开始读取固件。固件是固定在主板上的存储设备,里面有开机程序,开机程序将文件里面的操作系统加载到内存中运行。

\quad 操作系统启动,首先加载系统内核,然后启动初始化进程,编号为1,每个进程都有编号。接下来启动系统服务:文件服务,网络服务,安全服务,等待用户登录,输入密码登录/SSH登录。登录后,运行Shell(Linux中的bash是一种Shell,图形化界面也可以认为是一种Shell),用户就可以和操作系统对话了。
\quad 打开Windows中的任务管理器,查看系统进程:
\quad 当我们双击Chorme图标,系统会运行chorme.exe文件,开启Chorme进程作为主进程。主进程会开启一些辅助进程,如网络服务、GPU加速等。
\quad 在谷歌浏览器中,设置》更多工具》任务管理器下,可以看到浏览器启动的子进程:

2.浏览器的功能

  • 发起请求,下载HTML,解析HTML,下载CSS,解析CSS,渲染页面,下载JS,解析JS,执行JS等。
  • 功能模块:用户界面、渲染引擎、JS引擎、存储等,这些功能模块一般处于不同的线程中。

3.JS引擎

3.1 JS引擎举例
  • Chorme用的是V8引擎,用C++编写
  • 网景用的是SpiderMonkey,后被Firefox使用,也是用C++编写的
  • Safari用的是JavaScriptCore
  • IE用的是Chakra(JScript9)
  • Edge用的是Chakra(JavaScript)
  • Node.js用的是V8引擎
3.2 引擎的功能
  • 编译:把JS代码翻译为机器能执行的字节码或机器码
  • 优化:改写代码,使其更高效
  • 执行:执行上面的字节码或机器码
  • 垃圾回收:把JS用完的内存回收,方便以后再次使用

4 执行JS代码

4.1 准备工作

\quad 提供API:window/document/setTimeOut,这些内容都不是JS自身具备的功能,都是浏览器提供给JS的功能,我们把这些功能称之为运行环境runtime env
\quad 那么当JS代码被浏览器加载后,JS代码在哪里执行?答案是内存,内存图示:

\quad 红色区域用于存放数据,但不存放变量名称。

4.2 Stack和Heap

\quad Stack区数据顺序存放,Heap区数据随机存放。存储规律:非对象都存在Stack中,对象存在Heap中。 JS非对象的类型包括:数字,字符串,布尔值。

4.3 JS中的等号

\quad 与Java不同,JS中=总是会把右边的东西复制到左边。举例:

var p1 = {name:"zhangsan"};
var p2 = p1;
p2.name = "lisi";

那么,p1.name是什么?我是写Java的,第一次想当然的认为,当然是zhangsan。结果:

所以,在JS中不存在传值和传地址。
4.4 浏览器提供的对象
  • console
  • document
  • 对象
  • 数组
var a = [1,2,3] 等价于 var a = new Array(1,2,3)
  • 函数
function f(){} 等价于 var f = new Function()

上面列举出的对象,都是挂接在windows上的:

\quad 这样可以在任何地方直接使用。于此同时,还可以通过console.dir()打印对象的内存结构。举例:

5.JS的原型链

\quad 我们知道,在Java中,如果你声明了一个Object对象,那么是自带toString(),equals,hashCode方法的,那么在JS中呢?我们需要知道,JS中的对象都是有一个prototype属性的,如下图:

所以,我们声明一个对象,也是自动带有这些propertype中声明的属性。举例说明:

所以我们知道:JS中的所有对象都有一个隐藏属性,该隐藏属性存储了Object.propertype对象的地址,a.toString()发现a上没有toString(),就去隐藏属性对应的对象里面找,于是就找到了Object.propertype.toString()

如下代码:

var obj ={};
var array = [1,2,3]

内存图:

\quad 总结一下:XXX.prototype存储了XXX对象的共同属性,这就是原型。原型的存在,让我们无需声明对象之间重复的属性,可以省代码,省内存。于此同时,每个对象都有一个隐藏属性,指向原型对象。如下图: __proto__peototype都存储着原型的地址,只不过prototype挂在函数上,__prototype__挂在每个新生成的对象上。

6.参考文章