变量提升和函数声明提升

谁借莪1个温暖的怀抱¢ 2024-04-18 12:12 162阅读 0赞

变量提升和函数声明提升

之前一直在看变量提升和函数声明提升的讲解。看了很多但是实际操作中感觉掌握的还是不太好,索性整理一下

1.变量提升

变量提升的作用域是整个函数,var声明的函数会被提升到所在作用域的最顶端。意思就是说函数中的所有地方都是变量提升的范围,但是只会提升到所在作用域的顶端。

  1. function f (){
  2. console.log(y)//undefined
  3. var y = 1;
  4. }
  5. f();
  6. console.log(y);//报错

像在以上的代码中, 在运行后会先显示undefined再显示报错。这是因为一开始在f函数里运行的时候y进行了一次变量提升,但是并没有对y进行赋值操作,所以显示是undefined,而在f函数外再次进行输出时,由于y只在f函数里生效,所以会显示报错。
即一开始进行函数提升的时候是不会对其赋值的,赋值操作要等到后面用等于号进行。相当于是进行了以下操作:

  1. function f (){
  2. var y;
  3. console.log(y)
  4. y = 1;
  5. }
  6. f();
  7. console.log(y);

那如果外部还有一个变量的情况会怎么样呢?

  1. var y = 5;
  2. function f (){
  3. console.log(y)//这里会显示undefined,因为函数里已经有y了,所以会先优先输出函数里的y,但是函数里的y尚未赋值,所以为undefined。
  4. var y = 1;
  5. }
  6. f();
  7. console.log(y);//5,外部变量y赋值5

PS:另外要注意的是JS的函数之中是没有块级作用域的(现在的ES6中已经有块级作用域了)。只有全局执行环境(全局环境)和函数执行环境。

我们可以通过以下代码来加深印象:

  1. var i =5;
  2. function f() {
  3. console.log(i);
  4. if (false) {
  5. var i = 10;
  6. }
  7. }
  8. f(); =>undefined

这是因为在JS中是没有块级作用域的(即if判断语句里的i会变量提升到console.log前,所以输出undefined)。
相应的,我们再看一个类似的代码:

  1. var i =5;
  2. function f() {
  3. console.log(i);
  4. function k() {
  5. var i = 10;
  6. }
  7. }
  8. f(); =>5

结果为5是因为var i = 10; 这串代码是在k这个函数的执行环境里,变量声明提升也就只能到k函数的开头。所以当consolie.log需要一个i输出时,没法取到k函数里的i,只能从全局执行环境里找,即i为5。

也就是说,在代码执行之前编译器会对代码进行编译,并且会在该作用域的开头声明变量(也就是变量提升),而赋值操作是在代码执行时才会执行的。

要注意的是ES6中的let关键字声明的变量不会发生变量提升。

2.函数声明提升

函数的声明提升面对不同的声明方式是有区别的,对于函数声明是会进行函数提升的,而函数表达式是不会对其进行函数提升的。

函数声明

  1. console.log(one()); => 3
  2. function one() {
  3. var i = 1,j = 2;
  4. return i + j;
  5. }

这串代码由于one函数是函数声明而不是函数表达式,所以在编译的时候会跑到console.log前面,因而可以输出三。即以下代码:

  1. function one() {
  2. var i = 1,j = 2;
  3. return i + j;
  4. }
  5. console.log(one()); => 3

函数表达式

  1. console.log(one());=> 报错显示: Uncaught TypeError: one is not a function
  2. var one = function () {
  3. var i = 1, j = 2;
  4. console.log(i + j);
  5. }

这是因为在编译时代码实际为:

  1. var one;
  2. console.log(one());//此时只是将one这个函数名提升了,函数内部并没有提升。
  3. var one = function () {
  4. var i = 1, j = 2;
  5. console.log(i + j);
  6. }
所以总结下来就是编译时遇到函数声明会将整个函数声明提升,而函数表达式只是提升一个函数名,里面的内容并没有提升。
同时要注意的是当同时遇到函数声明和函数表达式时,会优先提升函数声明。
  1. console.log(one()); => 10
  2. var one = function () {
  3. var i = 1, j = 2;
  4. return i + j;
  5. }
  6. function one() {
  7. var i = 5, j = 5;
  8. return i + j;
  9. }

例如以上代码在运行时会输出10,因为函数声明会提示到console.log前面,并输出结果10。

发表评论

表情:
评论列表 (有 0 条评论,162人围观)

还没有评论,来说两句吧...

相关阅读

    相关 JavaScript变量声明提升

    变量提升 JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这