js中变量的声明与函数的声明提升
说到javascript变量的声明使用还真的和其他一下语言(java,c++)有一定的区别。主要因为js在执行过程中存在预编译过程,这个过程很独特,也很坑,接下来我们来看一下在js中变量的声明,赋值,函数的声明,赋值以及使用var,let,const,进行变量声明有什么差异。
变量的声明提升
1 | console.log(a); // undefined |
js引擎将这段代码预编译成:
1 | var a; |
我们在看一下这段代码
1 | var a = 3; |
js引擎将这段代码预编译成:
1 | var a = 3; |
通过这两段代码我们不难发现,js引擎在预编译js时候,将变量的(var)声明提到了该变量作用域的最顶端执行,注意:这里提到顶端仅仅是声明(var ‘变量名称’)这个过程,赋值的过程并没有被提升。让我们来看一下let:
1 | console.log(a); // ReferenceError: a is not defined |
1 | let a = 3; |
可见let声明变量并不会得到提升。
1 | var a = 3; |
重复声明不会报错但没有用当一次声明处理。1
2
3
4
5let a = 3;
let a; // SyntaxError: Identifier 'a' has already been declared
console.log(a) // 3
使用let 重复声明会报错
1 | var a = 3; |
控制台输出的是3,5,3。首先基本数据类型穿的参数遵循值的拷贝,所以外面的a值始终不变,函数形势参数相当于在函数内部声明一次,上面这段代码在预编译阶段被处理成这样:
1 | var a = 3; |
小伙伴们一定想看以下用let会是什么样:
1 | var a = 3; |
不出我们所料,重复定义直接报错,这这更佳证实了函数参数咱函数内部重新定义的理论。const 和let一样不会提升变量的声明,只是const声明变量修改就报错。
函数的声明提升
定义函数有多种方式我们来分析最常用的两种:
函数是声明(用function)
1
function a() {}
字面量形势声明
1
var a = function(){}
我们来看一下这段代码:
1 | a();// 1 |
这时候我们把函数形势声明注视掉:
1 | console.log(a);// undefined |
通过对比我们发现不注视之前我们在最上面调用a方法输出1,注视之后我们在最上面发现原本是a函数现在是undefined,我们来看一下第一段代码预编译做了些什么。
1 | var a; |
其实预编译时候是这样的,首先是变量的声明提升,接下来是函数式声明与赋值,(函数式声明赋值是一块的),然后是变量的赋值。
1 | var a = 2; |
在上面这段代码中函数内部a的值是这样变化的:
1 | var a ; |
总结
在js引擎预编译过程中,变量和函数的声明提升过程是这样的,首先是变量声明(var = 变量名),然后是函数式声明赋值过程,函数内部接受参数相当于var这个变量=传入的参数,最后才是根据程序上下文该赋值的赋值该输出的输出。这个过程中只有(var,function)声明过程被提升且由function 声明的函数声明赋值一块进行,var声明过程在function之前。