js代码执行分两个阶段:
预解析,提升声明
代码的执行:此阶段会产生全局的执行上下文
全局执行上下文和局部执行上下文:
当js代码刚开始执行时,会产生一个全局的执行上下文,当调用一个函数时,会产生一个局部执行上下文。一个局部执行上下文。
js中的声明:使用var来声明一个变量
变量的声明: 使用function来声明一个函数
在预编译期间:声明进行提升:提升的是加var的变量和function声明的函数。
1)加var的变量,在预编译阶段会提升,它仅仅是声明提升,并没有把赋值也提升。此时变量的值是undefiend。
2)使用function声明的函数也会提升,和变量不一样,它提升函数名,也提升函数值。
1)先创建一个全局的执行上下文(栈内存,全局栈)
数据的存储 声明的提升
2)代码执行
现在写的都是同步代码,浏览器开一个线程从上到下执行代码
3)如果遇见一个函数调用,产生一个局部的执行上下文(局部栈,函数栈)
在局部执行上下文中,代码也是分三个阶段:形参的赋值,声明的提升,代码的执行
在局部执行上下文中执行代码时,找一个变量,先在当前的执行上下文(作用域)中找,如果作用域中有这个数据,就使用当前作用域的,如果没有就去它的上一级执行上下文中去找。
1)作用域分为全局作用域和局部作用域,当声明了一个函数就会形成一个局部的作用域。
2) 一个局部的作用域都有上级作用域,上级作用域看的是函数声明,当调用一个函数时就会产生一个局部的执行上下文。
3)多个局部的执行上下文之间是没有关系的,在一个局部的执行上下文中要完成形参的赋值,声明的提升,代码的执行
4)当执行代码时,如果访问一个变量x,先看这个变量是不是自己上下文的,如果不是,就去找它的上一级作用域去查找,不只是查找一级,如果找不到会一直找到全局作用域。
5)此时形成一个链,叫做作用域链,也叫作用域链的查找机制。
(1)是函数内部的一个属性
1)一个局部的执行上下文(局部栈)有保护作用,保护它内部的数据(局部变量和函数声明)
形参是函数内部的局部变量。
2)每一个函数内部都有一个argumetns,是一个对象,称为伪数组(类数组)
3)函数调用时,实参会向形参赋值,不只给形参赋值,它还会把实参给arguments一份。
4)arguments.length可以获取实参的长度
(2)argument和形参之间的关系
1)当把形参的值改变了,那么arguments中的值也被改变了
2) 当arguments中的值改变了,那么形参的值也被改变了
3)形参和argumetns之间有一一对应的关系(a--->argument[0] b--->arguments[1])
(3)抛出来一个问题
arguments能代替形参存在吗?以后不写形参了可以吗?
如果形参有说明作用,通常就把形参写上去
如果形参没有说明作用并且传递给函数的实参特别多,那就不写形参了,通过arguments来接收实参。
为什么引出这一讨论?
在没有ES6中的let(块级作用域)和模块化之前,容易出现全局变量的污染
这个时候可以把自己的代码放到一个函数中,可以理解为手动调用,但是有弊端,因为有可能函数里还有函数。
所以这个时候IIEF出来了(声明完立刻就调用了)
有三种形式:
第一种形式:
;(function(){})()
第二种方式:
;(function(){}())
第三种方式:
+function(){}();
-function(){}();
!function(){}();
~function(){}();
------------------------------------------------当天小总结-----------------------------
关于全局执行上下文
局部执行上下文
代码的执行机制,一个代码运行起来的预解析门道有点深,慢慢画图去理解吧,
还有作用域链等等,语言不好描述,多研究一点此类型的图就Ok熟能生巧,时间久了一眼就能看出来结果就不需要画图了,现在还是老老实实画吧。