当前位置: 首页 > news >正文

js进阶——什么是提升

JavaScript 中的提升(Hoisting)是一个重要的概念,它指的是 JavaScript 引擎在代码执行之前,会将变量和函数的声明提升到它们所在作用域的顶部。这意味着,即使变量或函数在代码中后面声明,它们的引用可以在声明之前进行。不过,不同类型的声明(如 varletconst 和函数声明)在提升中的行为有所不同。

1. 变量提升(Variable Hoisting)

  • 使用 var 声明的变量:在函数或全局作用域内,变量声明会被提升到作用域顶部。但值的初始化并不会被提升,因此在变量声明之前访问该变量会得到 undefined。这是因为只有声明部分被提升,赋值部分保留在原来的位置。
示例:
console.log(x); // undefined
var x = 5;
console.log(x); // 5

上述代码在内部被处理为:

var x;
console.log(x); // undefined
x = 5;
console.log(x); // 5

注意:变量 x 在第一次 console.log 输出时已经被声明了,但还没有赋值,所以返回 undefined

  • 使用 letconst 声明的变量:虽然它们的声明也会被提升,但它们在声明之前不可访问。访问时会抛出 ReferenceError,这段不能访问的时间区间被称为暂时性死区(Temporal Dead Zone, TDZ)。
示例:
console.log(y); // ReferenceError: Cannot access 'y' before initialization
let y = 10;

解释y 在代码执行过程中是存在的,但在到达 let 声明之前,它位于 TDZ 中,因此访问会抛出错误。

2. 函数提升(Function Hoisting)

  • 函数声明(Function Declaration):完整的函数声明会被提升到其作用域的顶部。这意味着即使函数调用出现在函数声明之前,JavaScript 依然能够正确执行代码。
示例:
sayHello(); // "Hello, world!"function sayHello() {console.log("Hello, world!");
}

上述代码在内部被处理为:

function sayHello() {console.log("Hello, world!");
}sayHello(); // "Hello, world!"
  • 函数表达式(Function Expression):与变量提升类似,函数表达式中的变量会被提升,但实际的函数定义不会被提升。这意味着,如果在定义之前调用函数表达式,访问到的是 undefined,而非函数。
示例:
sayHello(); // TypeError: sayHello is not a functionvar sayHello = function() {console.log("Hello, world!");
};

解释sayHello 被提升为一个未定义的变量,因此在调用时返回 undefined,而不是一个函数,这会导致 TypeError

3. 类提升(Class Hoisting)

  • 类声明(Class Declaration):与 letconst 类似,类声明也会被提升,但同样会存在暂时性死区,在声明之前访问类会抛出 ReferenceError
示例:
let instance = new MyClass(); // ReferenceError: Cannot access 'MyClass' before initializationclass MyClass {constructor() {this.name = "Example";}
}

解释:虽然类声明被提升,但在其实际定义之前无法使用。

4. 提升的执行顺序

提升的顺序基于作用域的类型和声明的种类:

  • 在全局作用域中,var 声明的变量和函数声明会被提升到全局的最顶端。
  • 函数内部的变量和函数会被提升到函数作用域的顶部。
  • letconst、类声明会在作用域中被提升,但不可在提升前访问(即它们会被放入 TDZ 中)。

5. 提升带来的常见问题

提升有时会导致代码行为不符合直觉,特别是对于新手来说,可能会导致难以理解的错误:

  • undefined 错误:因为 var 提升,未初始化的变量会返回 undefined 而不是抛出错误。
  • 函数与变量同名:当变量名和函数名相同时,变量声明会覆盖函数声明。
示例:
console.log(foo); // ƒ foo() {}var foo = 10;function foo() {console.log("I am a function");
}console.log(foo); // 10

在这里,foo 首先被提升为函数声明,所以第一次 console.log 输出函数定义。但由于 var foo = 10 声明的变量在作用域中覆盖了函数,第二次输出的是数值 10

6. 小结

  • 变量提升var 声明的变量会被提升到作用域顶部,但在初始化之前值为 undefinedletconst 也会被提升,但会产生暂时性死区(TDZ),使得在声明前访问它们会抛出错误。
  • 函数提升:函数声明会完整提升,而函数表达式的变量会提升但值不会提升。
  • 类提升:类声明也会提升,但会像 letconst 一样进入暂时性死区。

掌握提升机制有助于理解 JavaScript 的执行流程,写出更清晰的代码。


http://www.mrgr.cn/news/33637.html

相关文章:

  • MySQL RANGE 分区规则
  • 求两个数二进制中不同位的数
  • UML——统一建模语言
  • Git 向远程仓库推送更改时加注释
  • OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【文件系统】上
  • 【comfyUI工作流】一键生成专属欧美漫画!
  • 视频怎么剪切掉一部分?6款视频剪切软件,零基础也能快速学会!
  • 【Java笔记】第12章:常用类
  • 基于单片机的无线宠物自动喂食系统设计
  • 实时同步 解决存储问题 sersync
  • 告别条件判断:策略模式让代码更优雅
  • c++类与对象一
  • AgentScope中带有@功能的多Agent组对话
  • python爬虫案例——异步加载网站数据抓取,post请求(6)
  • CCF csp认证 小白必看
  • error -- unsupported GNU version gcc later than 10 are not supported;(gcc、g++)
  • 条件编译及头文件包含
  • DAY78服务攻防-数据库安全RedisCouchDBH2database未授权访问CVE 漏洞
  • ModbusTCP通讯错误的排查
  • 数据处理与统计分析篇-day08-apply()自定义函数与分组操作