JavaScript 为什么要进行变量提升,它导致了什么问题?

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: JavaScript 为什么要进行变量提升,它导致了什么问题?

JavaScript 为什么要进行变量提升,它导致了什么问题?

  • • 无论是函数还是变量在那个位置上声明,都会被提升到函数之前,可保证变量声明前可访问而不会报错
  • • 变量提升的本质:js 引擎在代码执行前有一个解析的过程,会创建一个执行上下文,初始化一些代码执行所需要的参数。当访问一个变量时,会在当前执行上下文的作用域链中去查找,而作用域链的首端指向的是当前执行上下文的变量对象,这个变量对象是执行上下文的一个属性,它包含了函数的形参,所有函数和变量声明,这个对象是在代码解析的时候创建的。

代码执行过程:

  1. 1. 解析阶段:JS会检查语法,并对函数进行预编译。解析的时候会先创建一个全局执行上下文环境,先把代码中即将执行的变量、函数声明都拿出来,变量先赋值为undefined,函数先声明好可使用。在一个函数执行之前,也会创建一个函数执行上下文环境,跟全局执行上下文类似,不过函数执行上下文会多出this、arguments和函数的参数。
  • • 全局上下文:变量定义,函数声明
  • • 函数上下文:变量定义,函数声明,this,arguments
  1. 2. 执行阶段:按照代码顺序执行

为什么要进行变量提升?

  1. 1. 提高性能:在代码执行前,会进行语法检查和预编译,这个操作只会执行一次,这么做就是为了提高性能,如果没有这一步,则每次执行代码前都必须重新编译一下变量和函数,这是没有必要的,因为变量和函数的代码基本不会改变,解析一遍就够了。
  2. 2. 容错性更好
a = 1;
var a;
console.log(a); // 1

S(总结):

  • • 解析和预编译过程中的声明提升可以提高性能,让函数可以在执行时预先为变量分配栈空间
  • • 声明提升还可以提高JS代码的容错性,使一些不规范的代码也可以正常执行

导致的问题:

var tmp = new Date();
function fn(){
    console.log(tmp);
    if(false){
        var tmp = 'hello world';
    }
}
fn();  // undefined
/**
 * 在这个函数中,原本是要打印出外层的tmp变量,但是因为变量提升的问题,
 * 内层定义的tmp被提到函数内部的最顶部,相当于覆盖了外层的tmp,所以打印结果为undefined。
 */
for (var i = 0; i < 3; i++){
    setTimeout(() => {
        console.log(i);
    }, 2000);
} // 3 3 3
for (let i = 0; i < 3; i++){
    setTimeout(() => {
        console.log(i);
    }, 2000);
} // 0 1 2
/**
 * 由于遍历时定义的i会变量提升成为一个全局变量,在函数结束之后不会被销毁,
 * 所以,一直修改的是之前的定义的全局变量,所以第一个输出三次 3, 第二个输出 0 1 2。
 */
/**
 * 在 for 循环中,let 声明的变量会存在一个块级作用域的概念,使用 let 声明的迭代变量时,
 * js 引擎会在后台为每一个迭代循环声明一个新的迭代变量,因此每次使用的 i 都是不同的。
 */


文章特殊字符描述

问题标注 Q:(question)答案标注 R:(result)注意事项标准:A:(attention matters)详情描述标注:D:(detail info)总结标注:S:(summary)分析标注:Ana:(analysis)提示标注:T:(tips)

相关文章
|
7月前
|
前端开发 JavaScript Java
除了变量提升,JavaScript还有哪些特性?
【4月更文挑战第4天】JavaScript 特性包括函数作用域、动态类型、原型继承、异步编程、高阶函数、箭头函数、严格模式、对象字面量、模块系统和垃圾回收。这门语言支持多种编程模式,适合各种应用场景。想深入了解某特性,欢迎提问!😄
51 6
|
6月前
|
JavaScript 前端开发 开发者
JavaScript的变量提升是一种编译阶段的行为,它将`var`声明的变量和函数声明移至作用域顶部。
【6月更文挑战第27天】JavaScript的变量提升是一种编译阶段的行为,它将`var`声明的变量和函数声明移至作用域顶部。变量默认值为`undefined`,函数则整体提升。`let`和`const`不在提升范围内,存在暂时性死区。现代实践推荐明确声明位置以减少误解。
49 2
|
2月前
|
存储 JavaScript 前端开发
JS函数提升 变量提升
【10月更文挑战第6天】函数提升和变量提升是 JavaScript 语言的重要特性,但它们也可能带来一些困惑和潜在的问题。通过深入理解和掌握它们的原理和表现,开发者可以更好地编写和维护 JavaScript 代码,避免因不了解这些机制而导致的错误和不一致。同时,不断提高对执行上下文等相关概念的认识,将有助于提升对 JavaScript 语言的整体理解和运用能力。
|
2月前
|
JavaScript 前端开发 安全
JS中const有没有变量提升
JS中const有没有变量提升
23 0
|
6月前
|
JavaScript 前端开发
JavaScript中的变量提升(Hoisting)将`var`声明和函数声明提前到作用域顶部,允许在声明前使用
【6月更文挑战第25天】JavaScript中的变量提升(Hoisting)将`var`声明和函数声明提前到作用域顶部,允许在声明前使用。`let`和`const`不完全提升,存在暂时性死区(TDZ),尝试在初始化前访问会出错。函数声明会被提升,但函数表达式不会。
53 3
|
6月前
|
自然语言处理 JavaScript 前端开发
【JavaScript】JavaScript基础知识强化:变量提升、作用域逻辑及TDZ的全面解析
【JavaScript】JavaScript基础知识强化:变量提升、作用域逻辑及TDZ的全面解析
73 3
|
7月前
|
JavaScript 前端开发 开发者
【Web 前端】什么是JS变量提升?
【5月更文挑战第1天】【Web 前端】什么是JS变量提升?
【Web 前端】什么是JS变量提升?
|
5月前
|
JavaScript 前端开发 安全
20 JavaScript学习:变量提升和严格模式
20 JavaScript学习:变量提升和严格模式
|
6月前
|
JavaScript
JS 块级作用域、变量提升
JS 块级作用域、变量提升
|
7月前
|
JavaScript 前端开发
解释 JavaScript 中的变量提升现象。
JavaScript中的变量提升将变量和函数声明提前到作用域顶部。在代码执行时,即使声明在后,变量和函数也可访问。例如,`var a = 10;`在`console.log(a)`前已声明,故输出`undefined`。变量提升只提升声明,不提升赋值,未赋值变量默认为`undefined`。理解此特性对处理变量声明和作用域至关重要。
44 4