你可能不是真的理解Var声明提升,不信来看看

时间:2025-04-10 10:47:11

你好同学,我是沐爸,欢迎点赞、收藏、评论和关注。

JavaScript中,var 关键字用于声明变量。与 letconst不同,var 声明的变量具有函数作用域或全局作用域(如果声明在函数外部)。关于 var 声明的一个重要特性是声明提升(Hoisting)

声明提升

声明提升意味着无论 var 变量在函数的哪个位置声明,它都会被视为在函数顶部声明。但是,需要注意的是,只有变量的声明会被提升,而变量的初始化(即赋值)不会被提升。这意味着在变量被实际初始化之前,对于 var 来说,它会被视为 undefined

代码示例

function testVarHoisting() {
  console.log(a);
  var a = 2;
}

testVarHoisting(); // undefined
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

注意事项

  • 声明提升只影响声明本身,不影响初始化。
  • 使用 var 可能会导致意外的行为,特别是当在大型或复杂的代码库中时。因此,推荐使用 letconst 来声明变量,因为它们提供了块级作用域,减少了变量泄露到全局作用域或意外覆盖的风险。
  • 在严格模式(strict mode)下,未声明的变量会导致错误,这有助于捕获潜在的错误。然而,var 声明的变量仍然可以被提升。

练习题 1

function complexFunction() {
  console.log(a); // 输出什么?
  if (false) {
    var a = 10;
  }
  console.log(a); // 输出什么?
  var a = "Hello";
  console.log(a); // 输出什么?
}

complexFunction();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

答案:undefined,undefined,Hello 【if语句不影响var的变量提升,无论真假】

练习题 2

function complexFunction() {
  console.log(a); // 输出什么?
  if (true) {
    var a = 10;
  }
  console.log(a); // 输出什么?
  var a = "Hello";
  console.log(a); // 输出什么?
}

complexFunction();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

答案:undefined,10,Hello

练习题 3

console.log(x); // 输出什么?

var x = 2;

function f() {
  console.log(x); // 输出什么?
  var x = 3;
  console.log(x); // 输出什么?
}

f();

console.log(x); // 输出什么?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

答案:undefined,undefined,3,2

练习题 4

"use strict"; // 严格模式

console.log(x); // 输出什么?

var x = 2;

function f() {
  console.log(x); // 输出什么?
  var x = 3;
  console.log(x); // 输出什么?
}

f();

console.log(x); // 输出什么?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

答案:undefined,undefined,3,2 【严格模式不影响var的声明提升】

练习题 4

console.log(x); // 输出什么?

var x = 2;

function f() {
  x = 3;          // 输出什么?
  console.log(x); // 输出什么?
  var x = 4;
  console.log(x); // 输出什么?
}

f();

console.log(x); // 输出什么?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

答案:undefined,3,4,2【函数作用域的同名变量不会给外层变量赋值】

练习题 5

function test(x) {
  var x = "local";
  console.log(x); // 输出什么?
}

test(10);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

答案:“local”

function test(x) {
  console.log(x);  // 输出什么?
  var x = "local";
  console.log(x); // 输出什么?
}

test(10);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

答案:10,“local”【函数参数的优先级高于变量提升】

练习题 6

for (var i = 0; i < 3; i++) {
  setTimeout(function () {
    console.log(i); // 输出什么?
  }, 1000);
}
  • 1
  • 2
  • 3
  • 4
  • 5

答案:3,3,3 【var为全局变量,定时器回调在循环结束后执行】

练习题 7

var name = "World!";
(function() {
  if (typeof name === "undefined") {
    var name = "Jack";
    console.log("Goodbye " + name)
  } else {
    console.log("Hello "+ name);
  }
})();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

答案:Goodbye Jack 【逻辑同习题1,if语句不影响var的变量提升,无论真假】

练习题 8

var msg = "hello";
for (var i = 0; i < 10; i++) {
  var msg = 'hello' + i * 2 + i;
}
console.log(msg);
  • 1
  • 2
  • 3
  • 4
  • 5

答案:“hello189”【for循环内部的变量会覆盖外层的同名变量】

总结

如果上面的习题你都做对了,那你对var 变量提升问题的理解是比较深刻的,给你点赞????!

从以上习题中可以看出 var 声明变量存在很多"诡异"情况,特别是赋值前可以访问变量和重复赋值导致很多问题,你有时要看很久才能想明白执行顺序,这极不利于代码的维护,这也是提倡用 letconst 代替 var 的原因。项目开发中,同学们也应该尽量使用letconst代替var

好了,分享结束,谢谢点赞,下期再见。