深入了解JavaScript中let/var/function的变量提升

 更新时间:2022年07月25日 08:41:55   作者:​ 橘皮​  
这篇文章主要介绍了深入了解JavaScript中let/var/function的变量提升,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下

前言

在我们的印象中,当提到JavaScript中的变量提升,我们想到的是“变量和函数的声明在物理层面移动到代码的最前面“。当然这么说不大准确,变量和函数声明在代码里的位置是不会变的,而是在编译阶段被放入内存中。

可是如果我问你:let 到底有没有提升?如果有,var / let / function三者的变量提升一致吗?此时你的答案是什么?

接下来让我们来探讨这两个问题,如有错误敬请指正。

1. let存在提升

对于let是否存在提升这个问题,让我们先来看以下这段代码:

a = "global";
(function() {
    console.log(a); // undefined, 而不是打印出global
    var a;
}());

{
    console.log(a); // Uncaught ReferenceError: Cannot access 'a' before initialization
    let a = 1;
}

对于在函数作用域下打印出undefined,我们应该不奇怪。但引起我注意的是在块作用域下,抛出引用错误的原因是在初始化之前找不到a。那有没有可能a创建过程被提升?而在我发现ES文档中存在[var/let hoisting],这让我有理由猜测let存在提升,只是由于暂时性死区的原因,我们不能在let a之前使用 a

为了证明我的猜想,我想先从let声明的创建、初始化和赋值过程入手。

{
  let a = 0;
  a = 1;
}

上述的代码块中发生的过程如下:

  • 找到所有用let声明的变量,在环境创建变量;
  • 执行代码;
  • 执行a=0,将a初始化为1;
  • 执行a=1,对a进行赋值。

由该过程可知,如果我们在创建完变量后和初始化之前执行log()方法,控制台将会报错:

let a = 'global'
{
  console.log(a) // Uncaught ReferenceError: Cannot access 'a' before initialization
  let a = 1
}

由此一来我们就可以知道了let在创建的过程被提升,而在初始化过程没有被提升。

2. var/function的变量提升

接下来我们来看看function/var的创建、初始化和赋值过程,由此看看能否探究出它们的差别。

2.1 var的变量提升

function foo() {
  console.log(a);  // undefined
  var a = 0;
  var b = 1;
}
foo();

当我们执行foo()时,发生以下过程(较为省略):

  • foo创建环境;
  • 找到foo中所有被var声明的变量,在这个环境中创建变量;
  • 将变量初始化为 undefined;
  • 执行代码;
  • a赋值为0,b赋值为1。

由此我们可以知道var声明在代码执行前创建变量并初始化,所以当我们在var a = 0之前执行log(a)方法会得到 undefined 的结果。

2.2 function的变量提升

foo('btqf');

function foo(name) {
  console.log("my name is" + name)  // my name is btqf
}

当我们执行foo函数时,发生以下过程:

  • 找到所有function声明的变量,在环境中创建变量;
  • 将这些变量初始化并赋值;
  • 执行代码。

由此可见,function声明在代码执行前就创建、初始化并赋值。

3. 总结

  • let 的「创建」过程被提升了,但是初始化没有提升。
  • var 的「创建」和「初始化」都被提升了。
  • function 的「创建」「初始化」和「赋值」都被提升了。
  • 函数和变量相比,会被优先提升,即函数会被提升到更靠前的位置。

值得一提的是constlet基本类似,唯一的区别在于const只有创建和初始化,没有赋值过程。

到此这篇关于深入了解JavaScript中let/var/function的变量提升的文章就介绍到这了,更多相关let/var/function变量提升内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript封装Vue-Router实现流程详解

    JavaScript封装Vue-Router实现流程详解

    这篇文章主要介绍了JavaScript封装Vue-Router实现流程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-09-09
  • Javascript中神奇的this

    Javascript中神奇的this

    这篇文章主要为大家介绍了Javascript中神奇的this,何为this?this的作用有哪些、以及this神奇的绑定规则,感兴趣的小伙伴们可以参考一下
    2016-01-01
  • 使用JavaScript判断变量类型的方法详解

    使用JavaScript判断变量类型的方法详解

    在 JavaScript 中,变量的类型是动态的,这几天我在做项目时,遇到了一个从方法返回的值问题,为了避免这种问题,我需要先判断一下返回值的类型,那么,你知道哪些判断变量类型的方法呢,本文给大家介绍了使用 JavaScript 如何判断变量类型,需要的朋友可以参考下
    2024-06-06
  • uniapp组件之tab选项卡滑动切换功能实现

    uniapp组件之tab选项卡滑动切换功能实现

    这篇文章主要介绍了uniapp组件之tab选项卡滑动切换功能实现,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2023-01-01
  • JavaScript类型相关的常用操作总结

    JavaScript类型相关的常用操作总结

    这篇文章主要给大家总结介绍了关于JavaScript类型相关的常用操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-02-02
  • 微信小程序实现简易计算器功能

    微信小程序实现简易计算器功能

    这篇文章主要为大家详细介绍了微信小程序实现简易计算器功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-09-09
  • 如何自己实现JavaScript的new操作符

    如何自己实现JavaScript的new操作符

    new大家肯定都不陌生,单身没有对象的时候就new一个,很方便。那么它在创建实例的时候,具体做了哪些操作呢?今天我们就来一起分析一下。
    2021-04-04
  • JavaScript 动态三角函数实例详解

    JavaScript 动态三角函数实例详解

    本文通过实例代码给大家实例讲解了javascript动态三角函数知识,非常不错,具有参考借鉴价值,需要的朋友参考下
    2017-01-01
  • JScript内置对象Array中元素的删除方法

    JScript内置对象Array中元素的删除方法

    JScript内置对象Array中元素的删除方法...
    2007-03-03
  • Javascript 实现匿名递归的实例代码

    Javascript 实现匿名递归的实例代码

    本篇文章主要介绍了Javascript 实现匿名递归的实例代码,利用 arguments.callee 来实现匿名递归的方式。有兴趣的可以了解一下
    2017-05-05

最新评论