一切都运行在内存里
- 开机 操作系统在C盘里(macOS的在根目录下多个目录里)
当你按下开机键,主板通电,开始读取固件
固件就是固定在主板上的储存设备,里面有开机程序
开机程序会将文件里的操作系统加载到内存中运行
- 操作系统
-
首先加载操作系统内核(操作系统把最基础的功能都嵌入了内核里面,如上网、文件管理、显示等)
-
然后启动初始化进程,编号为1,每个进程都有编号。
(//在任务管理器中右键选中PID,PID就是编号) -
启动系统服务: 文件、安全、联网
-
等待用户登录: 输入密码登录/ssh登录
-
登录后,运行shell,用户就可以和操作系统对话了
-
bash是一种shell,图形化界面可认为是一种shell PS:
-
bash是一种shell,一个叫ba的人写的shell
-
操作系统的内核叫作kernel,提供的操作界面叫作shell,我们用shell和内核进行交互,比如:我们会命令它去新建一个文件,打开浏览器等。。
打开浏览器(chrome.exe)
- 你双击chrome图标,就会运行chrome.exe文件
- 开启chrome进程,作为主进程
- 主进程会开启一些辅助进程,如网络服务、GPU加速
- 你每新建一个网页,就有可能会开启一个子进程
浏览器的功能
发起请求、下载HTML、解析HTML、下载CSS、解析CSS 、渲染界面、下载JS、解析JS、执行JS等
PS:HTML提供节点,CSS提供节点样式,解析完HTML和CSS后,把他们合起来放到屏幕上,这个动作叫作渲染
功能模块:
用户界面、渲染引擎(解析完HTML和CSS并把他们合起来渲染的代码)、JS引擎、储存等
上面的功能模块一般各处于不同的线程(比进程更小)
如果进程是车间,那么线程就是车间里的流水线了
JS引擎
- Chrome用的是V8引擎,C++编写
- Safari用的是JavascriptCore
- IE用的是chakra(JScript 9)
- Node.js用的是V8引擎
主要功能
- 编译: 把JS代码翻译为机器能执行的字节码或者机器码
- 优化: 改写代码,使其更高效
- 执行: 执行上面的字节码或机器码
- 垃圾回收: 把JS用完的内存回收,方便之后再次使用
执行JS代码
准备工作: 提供API:window/document/setTimeout
上面这些东西都不是JS自身具备的功能(使浏览器提供给JS的功能)
我们将这些功能称为运行环境(runtime env),一旦把JS放进页面,就开始执行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
- 规律: 数据分两种:对象和非对象
非对象都存在Stack,对象都存在Heap
数组是对象、函数是对象
数字、字符串、布尔这三个不是对象,其他都是
“ = ” :等号总是会把右边的东西复制到左边(不存在什么传值和传址)
对象被篡改了
代码:
var person = {name : 'frank'}
var person2 = person
person2.name = 'ryan'
console.log(person.name) //'ryan'
JS开发者说要有window,就有了window(浏览器提供的)
还要有什么?
要有console
于是就有了console,并且挂到window上,可以用window.console查看
要有document
于是就有了document,并挂到window上,可以用window.document查看
要有对象
于是就有了Object,并且挂到window上
var person = {}
是简洁写法
var person = new Object()
是完整写法
var person = {}
等价于var person = new Object()
一般更倾向于简洁写法
要有数组(一种特殊的对象)
于是就有了Array,并且挂到window上
与上面一样,同理,
var a = [1,2,3]
等价于var a = new Array(1,2,3)
要有函数(一种特殊的对象)
于是就有了Function,并且挂到window上
同理,
function f() {}
等价于var f = new Function
怎么什么都挂window上?
因为方便,挂在window上的东西可以在任何地方直接使用。
比如,在window上挂xxx
window.xxx = function() {}
然后直接输xxx就可以调用函数
把window用内存图画出来
更简单的画法
console保存了console.log或者console.clear的地址
俗称window.console指向/引用了这个对象,保存了它的地址
细节
- 关于window
window变量和window对象是两个东西
window变量是一个容器,存放window对象的地址
window对象是Heap里的一坨数据
不信的话,可以让var x = window
,那么这个x就指向了window对象,window变量就可以去死了。。。
但是,这样容易弄晕新手
- 同理 console和console对象不是同一个东西
Object和Object函数对象不是同一个东西
前者是内存地址,后者是一坨内存
JS三座大山
- this 2. 原型链 3. AJAX
原型链
图里的prototype是干什么用的?
打印出来看看console.dir(window.Object.prototype)
当然window.可以省略
代码
var obj = {}
obj.toString()
为什么不报错,为什么可以运行?
- 因为:
obj有一个隐藏属性,隐藏属性储存了Object.prototype对象的地址
obj.toString()发现obj上没有toString,就去隐藏属性对应的对象里找。
于是就找到了Object.prototype.toString
代码
var obj2 = {}
obj2.toString()
obj2和obj有什么联系?
- 相同点 都可以调用.toString()
- 不同点 地址不同obj不等于obj2 可以拥有不同的属性
xxx.prototype储存了xxx对象的共同属性
这就是原型
原型让你无需重复声明共有属性,省代码、省内存
每个对象都有一个隐藏属性
这个隐藏属性指向原型
这个隐藏属性叫作__proto__
先关心小写字母的隐藏属性(obj...),不关心大写字母的隐藏属性(Object)
prototype和__proto__的区别是什么?
都存着原型的地址,只不过prototype挂在函数上。
__proto__挂在每个新生成的对象上。
- 代码
var arr = [1,2,3]
arr.join('-')
为什么不报错?为什么可以运行?
- 因为: arr有一个隐藏属性,隐藏属性储存了Array.prototype对象的地址
arr.join()发现arr上没有join,就去隐藏属性对应的对象里面找。
于是就找到了Array.prototype.join
Object和objec的区别是什么?
Object是一个全局函数,可以用来生成对象,var obj = new Object() 可以简写成var obj = {};
而object什么也不是,除非我声明一个var object
Object.prototype/Array.prototype/Function.prototype保存了一个对象的地址,这个对象包含了所有对象/数组/函数的共有属性,叫作对象/数组/函数的原型
每个对象都有一个隐藏属性,用来保存其原型的地址,这个隐藏属性的名字叫作__proto__