文章目录
一、预解析
1.什么是代码段?
一个script标签就是一个代码段。JS代码在执行时,是一个代码段一个代码段执行。
JS代码的执行分两个阶段:
JS代码在执行时,分成两个阶段,一个叫预解析,一个叫执行,预编译结束后,才会进入到执行阶段。
2.什么是预解析?
- (1)浏览器在执行JS代码的时候会分成两部分操作:预解析以及逐行执行代码
- (2)也就是说浏览器不会直接执行代码,而是加工处理之后再执行
- (3)这个加工处理的过程,我们就称之为预解析
预编译期间:
- (1)把声明提升:加var的变量就是被提升,function声明的函数也会提升,提升到代码段的最前面。
- (2)函数内部的局部变量,提升到函数体的最前面。
注意:变量的提升仅仅是声明函数的提升不只提升了声明,也提升赋值。
二、执行上下文和数据存储
1.全局对象
叫window 只要我们写的全局变量或在全局中写的函数,都会挂载到window上面。 GlobleObject===>GO 说白了,就是window对象
全局对象上,默认也有很多的东西,alert()…
2.执行上下文
代码分类:
(1)全局代码:函数外面的代码都是全局代码
(2)函数代码:一个函数就是一个局部代码
执行上下文:ExecuteContext ====>EC
全局代码执行产生ECG,每当调用一个函数,就产生一个函数的EC。每产生一个EC,需要放到ECS,当函数调用完毕,这个EC就是出栈,出栈后的EC,会被销毁,所谓的销毁指它们分配的内存空间都要被释放掉。
作用:给当前代码提供数据。全局执行上下文: 鸡蛋
当全局代码执行时,就会产生一个全局的执行上下文,EC(G);
局部执行上下文: 鸡蛋
当函数代码执行时,就会产生一个局部的执行上下文,EC(Fn)。只要调用一个函数,就会产生一个局部 执行上下文。调用100个函数,就会产生100个执行上下文。
执行上下文栈:
Execute Context Stack ===> ECS
栈:杯子
JS在执行代码时,肯定先执行全局代码,就会产生EC(G),这个EC(G)就要入栈。
当我们调用一个函数,就会产生一个局部的执行上下文,此时这个局部的执行上下文也要入栈。 当函数调用完毕后,这个EC就要出栈,又进入EC(G),当全局代码执行完后,EC(G)也要出栈。
3.数据存储
内存分区:
我们只需要掌握两个区,一个是栈区,一个是堆区。
基本数据类型,是存储在栈区的,引用数据类型是存储在堆区,堆区的地址,还是保存在栈区
4.加var的变量和不加var的变量的区别
- (1)加var的变量在预编译期间会提升,不加var的变量在预编译期间不会提升。
- (2)不管有没有加var,创建的变量,都会放到GO中的,也就是可以通过window.xx。
- (3)加var的变量,可能是全局变量,也可能是局部变量,不加var的变量,只能是全局变量。
- (4)加var的局部变量,不会作用window的属性
不加var创建的变量:
不好。 项目中尽量不要使用全局变量。在项目中,不要使用没有加var的变量。
5.使用let声明的变量的特点
(1)使用let声明的变量没有提升。
针对这个错误:ReferenceError: Cannot access ‘a’ before initialization
有人是这样说的:let声明的变量也有提升。但是没有赋值(没有初始化)
就记一种:使用let声明的变量也提升,只不过没有初始化,去使用的时候就报错了。
(2) 使用let配合{}会形成块级作用域。 在C语言中,就有块级作用域。
在JS中,原本是没有块级作用域。在块中声明的变量,只能在块中使用。
(3)使用let声明的变量并不会挂载到GO中
(4)使用let声明的变量也不能重复声明
在项目中不要使用var来声明变量,如果要声明变量,使用let。
使用var声明变量不足:
(1)提升
(2)重复声明
浏览器中有这样一个机制,如果一个变量提升过了,后面遇到同名变量,就不会提升了。
6.使用const声明的变量(常量)的特点
(1)声明的变量不能修改(常量)
(2)声明时必须赋值(初始化) 定义 = 声明+赋值(初始化)
(3)const声明的常量也不会提升。
(4)0const声明的常量配合{} 也会形成块级作用域
(5)const声明的常量也不会挂载到GO上。
总结:项目中不要使用var 如果声明变量使用let,如果声明常量,使用const。
7.JS中常见的错误
(1)语法错误
你的写代码 JS编译器不认识。 代码也没有进行预编译,更没有执行。解决非常简单 找到你的代码,哪里不符合人家的语法
(2)引用错误
当使用了一个没有定义的数据,可能就会报引用错误 解决:你的数据有没有定义出来特点:从引用错误开始,后面的代码就不会执行了
(3)类型错误
数据类型使用不当,你提供的数据类型,并不是JS所需要的数据类型, 解决:检测你的数据的数据类型。
(4)范围错误
在使用容器时,方式不对 容器:array object 特别是,使用长度(容器的大小)。
(5)逻辑错误:
它在控制台中不会错误,结果并不是我们需要的,打印的结果和我们想像的结果不一样。
解决:通过JS断点调试。
断点可以通过两个地方打:
1)通过代码 debugger bug虫子 debug调试错误
2)在浏览器的调试工具中打断点
附:执行上下文练习题