【JS】JS引擎

433 阅读6分钟

一、操作系统

一切都运行在内存里

(1)开机流程

  • 操作系统在C盘里
  • 当你按下开机键,主板通电,开始读取固件
  • 固件就是固定在主板上的存储设备,里面有开机程序
  • 开机程序会将文件里的操作系统加载到内存中运行

(2)打开操作系统(以Linux为例)

  • ①首先加载操作系统内核
  • ②然后启动初始化进程,编号为1,每个进程都有编号
  • ③启动系统服务(其他进程):文件、安全、联网(操作系统中包含最基本的操作,比如新建文件啥啥啥的,就不用下载软件去进行操作了)
  • ④等待用户登录:输入密码登录/ ssh登录
  • ⑤登录后,运行shell,用户就可以和操作系统对话了。
  • ⑥shell是操作界面,用于和内核进行交互。bash是一种shell,图形化界面可认为是一种shell。 注:如何查看进程:右击最下面的任务栏→任务管理器

(3)打开浏览器

  • 你双击Chrome图标,就会运行chrome.exe文件
  • 开启Chrome进程,作为主进程
  • 主进程会开启一些辅助进程,如网络服务、GPU加速
  • 你每新建一个网页,就有可能会开启一个子进程(如果打开域名相同的网页可能不会开启一个子进程) 注:如何查看Chrome里的进程:右上角三个点→更多工具→任务管理器

二、浏览器的功能

1.浏览器的功能

用户在浏览器的地址栏输入地址后发生了什么?

  • 发起请求
  • 下载HTML
  • 解析HTML
  • 下载CSS
  • 解析CSS
  • 渲染界面:意思是等HTML和CSS解析好后把它们组合起来显示到桌面上
  • 下载JS
  • 解析JS
  • 执行JS

2.浏览器的功能模块

  • 用户界面
  • 渲染引擎:是串代码,作用是把HTML和CSS组合起来显示到桌面上
  • JS引擎:是串代码,作用是解析并执行JS
  • 存储

3.线程

  • 功能模块一般各处于不同的线程(比进程更小)
  • JS只能单线程执行:一个标签页的进程里只有一个JS引擎线程,线程下又不能再开一个线程。
  • 跨线程通信:JS引擎不可以直接修改HTML和CSS,需要去寻找渲染引擎的帮助。所以跨线程通信肯定要比线程内的操作来得慢,就有了常听说的说法:DOM操作慢。

三、JS引擎

JS引擎举例

  • Chrome用的是V8引擎,C++编写
  • 网景用的是SpiderMonkey,后被Firefox使用,C++
  • Safari用的是JavaScriptCore
  • IE用的是Chakra (JScript9)
  • Edge用的是Chakra (JavaScript)
  • Node.js用的是V8引擎

主要功能

  • 编译:把JS代码翻译为机器能执行的字节码或机器码
  • 优化:改写代码,使其更高效
  • 执行:执行上面的字节码或者机器码
  • 垃圾回收:把JS用完的内存回收,方便之后再次使用

四、执行JS代码

1.准备工作

  • 浏览器提供API: window / document / setTimeout,这些统称为运行环境。
  • 一旦把JS放进页面、控制台,就开始执行JS 注:JS代码在内存中运行(当浏览器把JS代码下载下来后,存到了内存当中)

2.瓜分内存

一切程序都是运行在内存当中,所以程序们会瓜分内存。

1.所有程序运行后就会进入内存当中,参与瓜分内存

2.操作系统OS会瓜分一些内存

3.打开了Chrome浏览器,主进程会占据一些内存,然后辅助进程、各种新开的标签页会占据内存

4.细看其中一个标签页的进程,他占据的内存被细分为渲染引擎线程、用户界面线程、JS引擎线程等。而JS引擎线程占据的内存又被细分为代码区、不知什么区、数据区等等

代码区:所有JS代码放在里面,然后开始解析等

不知什么区:存放变量名、存放环境

数据区:存放数据,分为Stack栈和Heap堆。

  • Stack 栈 中存放非对象(如数字、字符串),每个数据顺序存放。
  • Heap 堆 c中存放对象(如数组、函数),每个数据随机存放。 代码示例
var a= 1
var b= a
var person = {name:'YY', child: {name: 'jack'}}
var person2 = person

注:JS所有数据都是64位

规律

  • 数据分为两种:非对象和对象
  • 非对象都在Stack(数字,字符串,布尔)
  • 对象都在Heap(数组,函数)
  • = 总是会把右边的东西复制到左边(不存在什么传值和传址)

Windows

1、浏览器提供window,很多东西挂在window

因为挂在window上的东西可以在任何地方直接使用

1.console

=window.console

2.document

=window.document

3.对象Object

=window.Object

  • Object 是一个全局函数,可以用来生成对象
  • var obj = new Object() ,可以简写成var obj = {}
  • object 什么也不是,除非我声明一个 var object

4.数组Array

  • =window.Array
  • Array是一个全局函数,可以用来生成数组(也是一种特殊的对象)
  • var a = new Array(1,2,3),可以简写成var a= [1,2,3]

5.函数Function(一种特殊的对象)

  • =winow.Function
  • Function是一个全局函数,可以用来生成函数(也是一种特殊的对象)
  • ar f= new Function(),可以简写成function f(){}

6.自己写个window.xxx=xxx

2、window在内存中的存放方式

  • window变量是一个容器,用来存放window对象的地址
  • window对象存在Heap堆。
  • window对象里有很多个属性,其中有个属性console指向一个对象;有个属性Object指向一个对象,这个对象是个函数,里面有很多属性;还有个属性Array指向一个对象,这个对象也是个函数,里面有很多属性 注:用console.dir(window.Object)打出结构,可见虽然是函数但是有很多属性

原型链

1.JS创建之初就已经给出了window.Xxx.prototype对象,它储存了xxx对象的共同属性,称为原型。

  • 比如window.Object.prototype对象储存了object对象的共同属性
  • 比如window.Array.prototype对象储存了array对象的共同属性 2.每一个xxx对象都有一个隐藏属性_ _ proto _ _,这个隐藏属性储存了window.Xxx.prototype的地址,也就是这个隐藏属性指向了window.Xxx.prototype这个对象,也就是隐藏属性指向共同属性,指向原型.
  • 比如obj是一个Object,obj的对象有一个隐藏属性_ _proto_ _,它指向window.Object.prototype对象。
  • 比如a是一个Array,a的对象有一个隐藏属性_ _proto_ _,它指向window.Array.prototype对象。

3.原型让你无需重复声明共有属性,省代码,省内存

4.prototype_ _ proto _ _ 都存着原型的地址,只不过prototype挂在函数上,_ _ proto _ _ 挂在每个新生成的对象上。

5.我们现在只研究函数(大写字母开头)的prototype和新生对象(小写字母开头)的_ _ proto _ _

6.共有属性我们可以读,但是修改了的话只能存放到自己的对象里,放不进共有属性里面,也就是我们改不了共有属性,只能修改共有属性在我们上