为什么此控制台日志受后续 if 语句的影响

Why is this console log affected by a subsequent if statement?

本文关键字:if 语句 影响 控制台 日志 为什么      更新时间:2023-09-26

请考虑以下代码:

var a = 'a';
function b() {
    console.log(a);
    if (!a) {
        var a = 'b';
    }
}
b();

运行b() undefined打印到控制台。但是,如果删除 if 语句,甚至只是从 if 语句中的表达式中删除 var 关键字,以便重新定义外部 a 变量,则字符串a将按预期打印到控制台。

谁能解释一下?我能想到的唯一原因是这是一个竞争条件,if语句的运行速度比console.log快一点。

这不是竞争条件 - 它是一种语言功能,并且按照Javascript语言的设计者的期望工作。

由于提升了变量定义

(其中函数范围内的所有变量定义都提升到函数的顶部(,因此您的代码等效于以下内容:

var a = 'a';
function b() {
  var a;
  console.log(a);
  if (!a) {
    a = 'b';
  }
}
b();

因此,本地声明的a隐藏全局声明的a,并且最初具有 undefined 的值,直到 if 语句为其提供值。

您可以通过搜索 "Javascript hoisting" 找到很多关于 Javascript 语言这一特征的讨论。

  1. 当您在函数中使用var语句时,它将创建一个该函数本地的新变量。

  2. 函数
  3. 中声明的所有变量都将移动到函数的顶部,而不管它们实际声明的位置如何。这称为吊装

  4. 默认情况下,提升的变量将具有值 undefined ,直到它们被显式分配一个值。

由于第 3 点,它按原样打印undefined

在您的情况下,您在if块中声明了一个变量a。由于变量被提升,因此声明被移动到函数的顶部。它与外部变量具有相同的名称。当您访问函数中的a时,它首先在当前作用域中查找是否存在该名称的变量。仅当在本地作用域中找不到其他作用域时,它才会检查其他作用域。因此,局部a遮蔽了外a.删除 var 语句时,本地作用域中没有a,因此使用外部a。这就是为什么它打印a.