前置知识: 在 JavaScript 中,“变量提升”(Hoisting)是指在代码执行之前,变量和函数声明会被提升到其所在作用域的顶部。对于使用 var 关键字声明的变量,会发生变量提升现象。
一、声明提升
1.变量声明提升: 无论 var
变量在代码中的何处声明,它都会被提升到其所在的函数作用域或全局作用域的顶部。例如:
console.log(a); // undefined
var a = 10;
在这个例子中,虽然变量 a
的声明在console.log
之后,但由于变量提升,在执行 console.log(a)
时,变量 a
已经存在于作用域中,只是还没有被赋值,所以输出 undefined
。
2.函数声明提升: 函数声明也会被提升到作用域的顶部。这意味着可以在函数声明之前调用函数。例如:
foo(); //Function called.
function foo() {
console.log('Function called.');
}
在这个例子中,函数 foo
在被调用之前声明,由于函数声明提升,代码可以正常执行并输出 Function called.
。
二、变量提升的影响
1.可能导致错误: 如果不了解变量提升,可能会在代码中出现意外的结果。例如,在变量赋值之前使用变量可能会导致 undefined 的值被使用,或者在函数声明和调用的顺序不清晰时可能会出现错误。
2.代码可读性和可维护性: 变量提升可能会使代码的可读性降低,因为代码的执行顺序可能与看起来的顺序不一致。这也会使代码的维护变得更加困难,特别是在大型项目中。
三、如何避免声明提升带来的问题?
使用ES6 中的 let 和 const: 声明的变量不会发生变量提升。
如果在声明之前使用 let 或 const 变量,会抛出 ReferenceError。
例如:
console.log(b); // ReferenceError: b is not defined
let b = 20;
总之,变量提升是 JavaScript 中使用 var 声明变量的一个特性,但在现代 JavaScript 开发中,建议使用 let 和 const 来声明变量,以避免由于变量提升带来的潜在问题,并提高代码的可读性和可维护性。
题目(源自字节前端题库 高频):
//请写出打印结果
var a=1;
function b() {
a=10;
return;
function a() {}
}
b()
console.log(a);
打印结果为 1
or 10
? 来看浏览器输出的结果:
以下是对这段代码的分析:
一、代码解读
var a = 1;
:在全局作用域中声明了一个变量 a 并初始化为 1。
function b() {...}
:定义了一个函数 b。
a = 10
;:尝试将变量 a 的值修改为 10。但在这个函数内部,由于存在一个名为 a 的函数声明,会导致变量提升,使得这里的 a 被视为局部函数名而不是外部的全局变量 a。
return;
:函数立即返回,不执行后面的代码。
function a() {}
:在函数 b 内部声明了一个函数,名为 a。这个声明会被提升到函数的顶部,在函数内部,这个局部的 a 会覆盖外部的全局变量 a 的引用。
b();
:调用函数 b。
console.log(a);
:在全局作用域中打印变量 a 的值。
二、结果分析
由于在函数 b
内部的函数声明导致了变量提升,并且在函数内部对a
的赋值被视为对局部函数a
的操作,而不是对全局变量a
的操作。所以全局变量 a
的值始终保持为初始值 1
。最终控制台输出 1
。