JS基本概念
- 借鉴C语言的基本语法
- 借鉴Java语法的数据类型和内存管理
- 借鉴Scheme语言,将函数提升到“第一等公民”(first class)的地位
- 借鉴Self语言,使用基本原型(prototype)的继承机制
JS是单线程语言。
浏览器多进程、多线程
浏览器打开一个网页相当于新开了一个进程,进程有自己的多线程
-
Browser 进程(浏览器的主进程,只有一个)
- 页面显示,与用户交互,比如前进、后退
- 管理各个页面,创建和销毁其他进程
- 网络资源管理,比如下载
-
第三方插件进程
- 每个类型的插件对应一个进程,进党使用插件时才创建
-
GPU 进程
- 最多一个,用于3D 绘制
-
浏览器渲染进程(浏览器内核)
- 默认每个tab 页一个进程,互不影响
- 页面渲染,JS脚本执行,事件处理等
浏览器的渲染进程是多线程的
-
GUI 渲染线程
- 负责渲染页面,解析HTML,CSS,构建DOM 树,和RenderObject 树,布局和绘制等
- 当页面需要重绘(Repaint)或者回流(Reflow)时,该线程就会执行
- GUI 线程与JS 线程互斥,当JS 引擎执行时,GUI 线程会被挂起,GUI 更新会被保存在一个队列中,等JS 线程空闲时立即执行
-
JS 线程
- 也称JS 内核,负责解析JS 脚本,运行代码
- 一直等待任务队列中的任务,一个tab 页永远只有一个js 线程
- 当JS 线程执行代码时,会将对应任务添加到事件线程中
-
事件触发线程
- 归属浏览器,而不是JS 线程,用来控制事件循环
- 当事件被出发时,该线程会把事件添加到待处理队列的队尾,等待JS 引擎处理
- 由于JS 是单线程,所以队列中事件都要排队等待JS 线程处理,当JS 引擎空闲时才会执行。
-
定时器触发线程
- 比如setInterval 和 setTimeout
- 浏览器的计时器并不是由JS 线程提供的,在计时完毕后,添加到事件队列中,待JS 引擎空闲后执行,所以JS 计时器不准
- setTimeout 中低于4ms 的时间间隔算为4ms
-
异步http 请求线程(网络线程)
- 在XMLHttpRequest 在连接后是通过浏览器新开的一个线程请求
- 检测到状态变更时,如果有回调函数,异步线程就产生状态变更事件,将这个回调放到事件队列中,再由JS 线程执行
JS特点
- 单线程
JS只能在JS线程上运行,但是JS线程和GUI线程互斥,JS线程和GUI线程只能保持一静一动的状态。
- 由于JS 线程可以操作DOM,如果在修改这些元素属性同时渲染页面,那么渲染线程前后获得的元素数据就可能不一致了
- 为了防止渲染出现不可预期的结果,浏览器设置GUI 渲染线程与JS 线程为互斥关系,当JS 线程执行时,GUI 线程会被挂起
- GUI 更新会被保存在一个队列中,等到JS 引擎线程空闲时立即执行
- 动态、弱类型
运行时才确定数据类型的语言,变量在使用之前无需声明类型
const name = 'haha';
与之相对的就是,静态、强类型语言
编译时变量的数据类型就需要确定的语言
Sring name = 'haha';
简单数据类型
string ,number,boolean,undefined,null
值类型变量的数据直接存放在变量(栈空间)中
引用类型(复杂数据类型)
通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中
const a = {
name: '11';
}
const b = a;
b.name = '222';
console.log(a, b);
对于复杂类型,存放的是变量的地址,所以将a赋值给b的时候,也就是将a的地址给了b,所以最后改变b的时候,也就是改变了地址所指向的那个变量。
const str = '111';
let newStr = '222';
console.log(str, newStr);
我们可以看到str的值并没有像上面的name属性值一样发生改变,因为对于基础数据类型赋值的时候的是给的原始的值
const arr = [1, 2];
arr.push(3);
const str = 'strstrstr';
str.slice(0, 2);
console.log(arr, str);
在JS中,复杂的数据类型的原始值是可以被改变的,但是基础类型的原始值是不可以被改变的。
作用域