【问题标题】:logging a global variable using var vs let yields different results使用 var vs let 记录全局变量会产生不同的结果
【发布时间】:2018-10-11 05:19:32
【问题描述】:

在提供的代码中,我在 VSCode 中得到的 console.log() 语句与在 Chrome 控制台中不同。就像现在的代码一样,当我在 VSCode 中运行此代码时,输​​出为 undefined,但是当我在 Chrome 控制台中运行此代码时,输​​出为 Nimit Maru。
如果我将第 1 行中的 var 关键字更改为 let(或 const),我会在 VSCode 和 Chrome 控制台中得到 undefined。
最后,如果我完全删除 var/let 关键字,并使用 fullName = 'Nimit Maru'; 运行第 1 行,我在 VSCode 和 Chrome 控制台中的输出都是 Nimit Maru。

我知道 let 关键字通常更适合本地范围,而 var 关键字将提升到全局范围,但我认为这不能解释为什么我从一个控制台得到不同的结果下一个。看到这个变量是在全局范围内定义的,我认为这不会有什么不同。

var fullName = 'Nimit Maru';

let myObj = {
  fullName: 'David Yang',
  property: {
    fullName: 'Omri Bernstein',
    getFullName: function() {
      console.log(this.fullName);
    },
  },
};

let whosName = myObj.property.getFullName;

whosName();

感谢您提供的任何见解。

【问题讨论】:

  • the var keyword will hoist to global scope 那句话是不正确的,因为它在谈论两个不同的概念,好像它们是相关的。更具体地说,提升不会改变范围——它只是意味着声明将被处理,就好像它在在同一范围内更进一步。
  • As the code is now, when I run this in VSCode 我一直在考虑这个问题,最初我以为你的意思是“当我运行我在 VSCode 中编写的代码作为应用程序的一部分时”,但现在我相信你可能意味着存在VSCode 提供的一些 REPL 工具,类似于控制台。那是对的吗?如果是这样,请注意它可能会以不同方式 运行您的代码 - 它很可能将其包装在一个函数中,在这种情况下,您看到的行为是预期的行为。我认为 Firebug 过去是这样做的,这意味着用它和其他地方编写的代码可能会略有不同
  • 抱歉没有说明清楚。我只是使用 Node.js 在 VSCode 的终端中执行这个 sn-p 代码。我认为您正在做某事.. 我了解全局范围与 Node.js 内部(在 VSCode 中)与 Chrome 的 window 对象内部有很大不同。所以我相信你是对的,这个sn-p很可能是在调用的时候被包裹起来的。

标签: javascript visual-studio-code google-chrome-devtools


【解决方案1】:

var 顶级变量自动分配给window 对象的属性。 let 和 const 变量不会发生此行为:

var varName = 'foo';
let letName = 'bar';
const constName = 'baz';
console.log(
  window.varName,
  window.letName,
  window.constName
);

当你调用whosName(); 时,你调用它时没有调用上下文,所以this 默认为window。因此,函数内部的this.fullName 将引用window.fullName,只有在您使用var fullName 时才会定义它。 (如果你使用了let fullName或const fullName,它就不会被分配给window,导致undefined。)

如果您想引用内部对象 (Omri Bernstein) 的 fullName属性,请使用 bind 或另一个调用 myObj.property.getFullName 的函数并带有适当的调用上下文:

let myObj = {
  fullName: 'David Yang',
  property: {
    fullName: 'Omri Bernstein',
    getFullName: function() {
      console.log(this.fullName);
    },
  },
};

let whosName1 = () => myObj.property.getFullName();
let whosName2 = myObj.property.getFullName.bind(myObj.property);

whosName1();
whosName2();

我知道 let 关键字通常更适合本地范围,而 var 关键字将提升到全局范围

这是不正确的。 var 具有 function 范围并被提升,而 const 和 let 具有 block 范围。使用var 声明的变量的作用域是它最近的周围函数,如果没有函数,则为顶层。

【讨论】:

  • 这很有道理,谢谢。我仍然很好奇我从 VSCode 的终端到 Chrome 的控制台得到的结果的差异。这只是从 Node.js 到 chrome 的 Window 对象处理全局对象的方式不同吗?
  • 我无法在堆栈 sn-p 或 JSFiddle 等普通 JS 环境中重现该问题 - 我认为 VSCode 会自动将您的代码包装在 IIFE 或其他东西中(这是有道理的,以避免不必要的全局污染),因此您的vars 没有被分配到窗口。
  • 澄清一下,我使用的是 VSCode 和 Node.js,只是在内置终端中运行这个 sn-p 代码,然后在 Chrome 控制台中运行相同的代码。所以我开始理解为什么会有这样的差异,因为运行时环境完全不同并且处理“全局范围”的方式不同。感谢您的意见!
猜你喜欢
  • 2020-12-06
  • 1970-01-01
  • 2017-08-18
  • 2018-01-20
  • 1970-01-01
  • 1970-01-01
  • 2021-08-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多