js基本概念
-
单线程: GUI线程和JS线程不能同时执行,互斥。
-
动态,弱类型 定义变量不需要指定类型,而在其他语言中,比如C,C++都需要指定类型
-
面向对象,函数式
-
解释类语言 JIT
JS是一种解释型语言,程序在运行时边编译边运行,因此需要用到解释器才可执行代码,且执行效率天生比编译型语言低
JIT:即时编译,是一种编译技术,它可以在运行时将代码编译为机器语言,以提高程序的执行效率。
- 安全,性能差
JavaScript是一种基于对象和事件驱动并具有相对安全性的客户端脚本语言。它不允许访问本地的硬盘,不能将数据存入服务器,不允许对网络文档进行修改和删除。边解释,边执行,所以性能会相对差,
数据类型
分为基本数据类型,和引用数据类型(对象) 与cpp,Java不同,js的字符串也属于基本数据类型,其他都一样
作用域
规定了变量分为可访问性和可见性,作用域分为动态作用域和静态作用域。
js是静态作用域,通过作用域可以知道代码如何查找标识符。
js中的作用域分为三种,全局作用域,函数作用域,块作用域。如下:
变量提升
变量提升(hoisting)是JavaScript中的一个特性,它指的是在执行代码之前,变量和函数声明会被移动到它们所在作用域的顶部。
//let const定义的变量没有变量提升,所以不能在定义前使用
console.log('company', company);//err
console.log('dep', dep);//err
// var定义的变量有变量提升,相当于在使用前声明这个变量并且被初始化为 undefined
console.log('myname', myname);//undefined
// 函数也有变量提升
// 在声明前使用该函数,发生函数提升,把函数的定义提到前面并且被初始化为 undefined
showInfo();// 正常输出
// var show = undefined 提升
show();// err show不是一个函数
const company = "Bytedance";
let dep ="边缘云";
var myname = "unkown";
function showInfo(){
console.log(company, dep, mynane);
console.log(myname);
}
var show = function () {
console.log(myname);
}
js是怎么执行的
执行上下文
词法环境中存储了当前执行上下文中所有的本地变量、函数声明、形参等信息,以及对外部词法环境的引用。 (感觉类似于os的中断处理)
当JS 引擎解析到可执行代码片段(通常是函数调用) 的时候,就会先做一些执行前的准备工作,这个准备工 作,就叫做“执行上下文( execution context简 称EC ) " ,也叫执行环境
调用栈: (图中 func应该放在词法环境中)
在调用栈中有一个ESP指针,指向栈顶空间,即当前运行的函数
词法环境、变量环境、outer
- 词法环境: 存放let const 定义的变量以及函数。
- 变量环境:存放var 定义的变量。
- outer:指向外部函数的一个指针。
(js可以在函数里面定义函数)
堆和栈
基本类型:采用的是值传递。
引用类型:则是地址传递。
引用类型的数据的地址指针是存储于栈中的,将存放在栈内存中的地址赋值给接收的变量。当我们想要访问引用类型的值的时候,需要先从栈中获得对象的地址指针,然后,在通过地址指针找到堆中的所需要的数据(保存在堆内存中,包含引用类型的变量实际上保存的不是变量本身,而是指向该对象的指针)。
js进阶知识点
this
在 JavaScript 中,this 关键字的指向取决于函数的调用方式。下面是一些常见的情况:
-
在全局作用域中,
this指向全局对象。在浏览器中,全局对象是window对象。直接输出this时,值为 global -
其他情况类似java和cpp ,另外可以使用
call、apply或bind方法显式地设置this指向的值。
var value='I am global';
function func() {
console.log(this.value);
}
let obj = { value: 'I am object' };
func.call(obj); // 输出 'I am object' 让this指向obj ,同样apply,bind都可以
垃圾回收
v8对GC(回收垃圾的)的优化
分代式垃圾回收:v8 的垃圾回收策略主要基于分代式垃圾回收机制,V8 中将堆内存分为新生代和老生代两区域。
新生代垃圾回收:新生代空间比较小,内存分为对象区域和空闲区域。 1.垃圾标记 ,将数据标记出来:哪些是垃圾哪些是活跃数据。
2.对象复制 ,把对象(即活跃的数据)复制到空闲区。
3.区域反转 ,对象区和空闲区反转,然后清除空闲区,原来的对象现在是在对象区。
新生代回收使用并行回收提高效率,并行回收依然会阻塞主线程
老生代垃圾回收
对象占用空间过大,新生代区存放不下时就存放在老生代区,另外新生代区中经过两次没有被清除掉的数据会放到老生代区
老生代垃圾回收采用标记整理算法,标记出垃圾数据并清理,然后整理内存,空出连续的内存
垃圾清理时js停止执行,以防在清理时引用到垃圾数据。
另外采用增量标记、惰性清理,并发回收提高效率
增量标记是指将一次垃圾回收的过程分为很多个小部分,每次执行完一小块,就让应用程序执行一会,交替执行。增量标记采用三色标记法(暂停与恢复)与写屏障(增量中修改引用)
惰性清理指的是让js脚本先执行,也无需一次性清理完所有非对象内存。
并发回收:主线程在执行 JavaScript 的过程中,辅助线程能够在后台完成执行垃圾回收的操作,辅助线程在执行垃圾回收的时候,主线程也可以自由执行而不会被挂起
事件循环
js代码主要分为两大类: 同步代码、异步代码
-
异步代码又分为:微任务与宏任务
-
事件循环Event Loop执行机制
-
1.进入到script标签,就进入到了第一次事件循环.
-
2.遇到同步代码,立即执行
-
3.遇到宏任务,放入到宏任务队列里.
-
4.遇到微任务,放入到微任务队列里.
-
5.执行完所有同步代码
-
6.执行微任务代码
-
7.微任务代码执行完毕,本次队列清空 (一次执行完所有微任务)
-
寻找下一个宏任务,重复步骤1 (每一个宏任务执行完都检查是否有新增微任务,有就先把这些新增的微任务全执行完)
以此反复直到清空所有宏任务,这种不断重复的执行机制,就叫做事件循环
宏任务主要包含:script( 整体代码)、setTimeout、setInterval、I/O、UI 交互事件、setImmediate(Node.js 环境)
微任务主要包含:Promise、MutaionObserver、process.nextTick(Node.js 环境)
-
写在最后
笔记参考@胡萝卜会飞 大佬的(字节青训营-深入理解js - 掘金 (juejin.cn))
大家的目光都在烟花上,但是,对不起,我却无法,把目光从这侧脸上移开,心跳的声音实在太吵了,连烟花的声音都听不到了。