JS中的变量提升

一、变量提升是什么?

1.1 一个变量提升的例子

console.log(myName)
var myName = 'xiaoming'
showName()
function showName() {
    console.log('xiaoli')
}

执行结果如下:

AB1462FF-A0B6-427A-8353-D8A49F775726.png

可以看到,在声明变量前打印变量,打印出的是 undefined;在声明函数前执行函数,则会直接执行。
这是为什么?

二、变量提升是怎么发生的?

2.1 声明与赋值

在了解为什么变量提升前,先要弄清楚什么是声明,什么是赋值

  1. 变量声明与赋值
var myName = 'xiaoming'

上面这行代码,其实是两行代码:

var myName    // 声明语句  其中 var 是声明语句的关键字
myName = 'xiaoming'     // 赋值语句
  1. 函数声明与赋值
function showName() {
    console.log('xiaoli')
}

上面这行代码整体,是一个函数声明语句,其中 function 就是函数声明的关键字

var showName = function() {
    console.log('xiaoli')
}

这行代码虽与之前的代码执行结果一样,都有了一个函数 showName,但真正的执行过程却不同。
这行代码可以分为两行代码:

var showName     // 声明语句   var 是关键字
showName = function() {
    console.log('xiaoli')
}                  // 赋值语句

这样拆开是不是清楚多了?和变量一样,也是先声明,后赋值,只是赋的值是一个函数而已。

2.2 JS 的执行过程

上面分清楚了声明与赋值,就可以来讨论下在 JS 代码究竟是如何执行的了。

  1. 编译
    在浏览器中运行的代码会先进行编译,在编译后,会生成两个东西:
    执行上下文、可执行代码。
    执行上下文就是 JS 代码的运行环境,里面会保存变量、函数、函数的this指向、函数的参数等信息。所有的声明语句都会在编译时被解析并保存在对应的上下文中。
    可执行代码按字面理解就是“可以被执行的代码”。那什么代码可以被执行呢?目前我的理解是:除了声明语句之外的语句,比如赋值语句、函数调用语句等

  2. 执行
    在这个过程,就是我们熟悉的 JS 引擎会一行一行地执行编辑阶段生成的可执行代码

2.3 变量提升是如何发生的

到现在为止,所有的了解变量提升前需要了解的内容都了解了。来讨论下开头的那个例子:

console.log(myName)
var myName = 'xiaoming'
showName()
function showName() {
    console.log('xiaoli')
}

我们来模拟一下代码的执行过程:

2.3.1 编译阶段:

  1. 生成全局的执行上下文。第一行放入执行代码
  2. 第二行拆分成两行代码:
1  var myName
2  myName = 'xiaoming'

执行第一行时,在全局执行上下文中放入一个变量:

globalContext: {
    myName: undefined
}

将第二行放入可执行代码

  1. showName() 这行代码放入可执行代码
  2. 识别出最后一句代码是赋值语句,在全局执行上下文中放入一个变量:
globalContext: {
    myName: undefined,
    showName: function(){console.log('xiaoli')}
}
// 实际情况下,函数会被存储在堆里,这里的 showName 存储的只是函数的引用

2.3.1 执行阶段:

  1. 执行第一行代码 console.log(myName),在目前的全局上下文中寻找 myName 变量,发现值为 undefined,打印出 undefined
  2. 执行第二行代码 myName = 'xiaoming' ,将全局上下文中的 myName 变量的值改为 'xiaoming'
  3. 执行第三行代码 showName() ,在目前的全局上下文中寻找 showName 变量,发现存在,且值为函数,执行这个函数,打印出 'xiaoli'
    最终,打印出的值如下:
// undefined
// 'xiaoli'
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1. 什么是变量提升? 当栈内存(作用域)形成, JS代码自上而下执行之前,浏览器首先会把所有带var/funct...
    _hider阅读 2,968评论 0 2
  • 像变量提升和函数提升这种偏学院派的问题在面试中出现的概率很高,在实际开发中也会影响到编程的效率。 前段时间在网上做...
    时和岁稔阅读 1,088评论 1 7
  • js和其他语言一样,都要经历编译和执行阶段。而js在编译阶段的时候,会搜集所有的变量声明并且提前声明变量,而其他的...
    Mica_马超阅读 592评论 0 0
  • /** *js中变量声明未赋值结果是undefined *js中没有声明变量结果报错 *js中的就近原则 *var...
    郑军基阅读 164评论 0 0
  • 当浏览器加载 HTML 页面时,首先会提供一个全局的执行环境,称为全局作用域,浏览器中是 window(既是一个窗...
    McDu阅读 281评论 0 0