- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
正如我们所知,传统上 JS 一直缺乏 block 作用域。正如我们所知,直到最近,JS 才只有函数作用域。
虽然在最近的 JS 版本中,我们可以使用 let
和 const
变量,它们仅在定义它们的范围内可见。
但是……在内心深处……这究竟是如何完成/实现的?现在语言中是否真的有 JS 中 block 作用域的一流概念,或者 block 作用域只是一些模拟,使某些变量仅在定义它们的 block 中可见?
我的意思是在最近的 JS 版本中 block 作用域是一流的东西,就像函数作用域一样,或者 block 作用域只是某种模拟,而我们实际上仍然只有旧的好函数范围?
最佳答案
But... deep down... how is this done/implemented really? Is there really now in the language a first-class notion of block scope in JS...?
是的,有。一个新 block ¹创建一个新的 lexical environment与创建函数的方式相同(显然,没有创建函数的所有其他方面)。你可以在 Evaluation section 中看到规范中的 block 数。
这是一流的语言结构。
¹ 我最初写“...包含一个let
、const
或class
声明...” 但是规范实际上并没有做出这种区分,尽管我希望 JavaScript 引擎会这样做(因为如果没有词法声明的绑定(bind)就不需要新的环境)。
在您提出的评论中:
What about hoisting? I read that block scoped-variables are hoisted to the top of the block they are defined in... but then also... You get an error if you try to access a block-scoped variable before the line/statement where it is declared in its block? This sounds contradictory, no? If they are hoisted we would not be getting this error but we would be getting undefined. What is the truth here?
在my book我将它们描述为半提升:变量的创建(更一般地说,“绑定(bind)”)被提升到其声明范围的顶部(let x
或其他)出现(在本例中为 block ),但绑定(bind)不会初始化,直到在逐步执行代码。创建和初始化之间的时间称为时间死区。您不能(根本)在 TDZ 内使用绑定(bind)。
这仅适用于 let
、const
和 class
声明。 var
有两种不同的处理方式: 1. 显然,var
被提升到函数(或全局)作用域的顶部,而不仅仅是 block 作用域。 2. 不太明显的是,var
绑定(bind)在进入作用域时同时创建和 初始化(值为undefined
)。它们已完全吊起。 (它们的声明是;var
语句上的任何初始化器实际上是一个赋值,并在代码的逐步执行中到达该语句时完成.)
这是一个例子:
function foo(n) {
// `l1` and `l2` don't exist here at all here
// `v` is created and initialized with `undefined` here, so we can happily
// do this:
console.log(`v = ${v}`);
if (n > 10) {
// `l1` and `l2` are created here but not initialized; if we tried to
// use them here, we'd get an error; uncomment this line to see it:
// console.log(`l1 = ${l1}`);
console.log("n is > 10");
var v = "a"; // `v` is assigned the value `"a"` here, replacing the
// value `undefined`
let l1 = "b"; // `l1` is initialized with the value `"b"` here
console.log(`l1 = ${l1}`);
let l2; // `l2` is initialized with the value `undefined `here
console.log(`l2 = ${l2}`);
l2 = "c"; // `l2` is assigned the value `"c"` here, replacing the
// value `undefined`
console.log(`l2 = ${l2}`);
}
}
foo(20);
为了完整起见,function
声明也是完全提升的,但比 var
更甚:函数实际上是在进入作用域(与 var
不同,后者获取值 undefined
)。
在您观察到的评论中:
Then... I don't see what's the difference between no hoisting and half-hoisting...
很好,我没有解释。区别与外部作用域中的隐藏 标识符有关。考虑:
function foo() {
let a = 1;
if (/*...*/) {
console.log(`a = ${a}`);
let a = 2;
// ...
}
}
日志应该显示什么?
抱歉,这是个骗人的问题;日志没有显示任何内容,因为您尝试在那里使用 a
时出错,因为内部 a
声明 shadows (隐藏)外部 a
声明,但内部 a
尚未初始化,因此您还不能使用它。它在 TDZ 中。
可以可能使外部a
在那里可访问,或者使内部a
在那里可访问,值为undefined
(例如,像 var
一样完全提升它,但只是在 block 内),但这两个都有 TDZ 帮助解决的问题。 (特别是:使用外部 a
会让程序员感到困惑 [a
在 block 的开头意味着一件事,但在后面又意味着另一件事?!] 并且意味着 JavaScript引擎必须在所有地方创建新的词法环境,基本上每个 let
或 const
或 class
都会引入一个新词法环境。并且预初始化undefined
让程序员感到困惑,因为 var
多年来向我们展示了...)
关于javascript - JavaScript 中真的有 block 作用域吗(作为一流的语言概念)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58622919/
我有一个 html 格式的表单: 我需要得到 JavaScript在value input 字段执行,但只能通过表单的 submit .原因是页面是一个模板所以我不控制它(不能有
我管理的论坛是托管软件,因此我无法访问源代码,我只能向页面添加 JavaScript 来实现我需要完成的任务。 我正在尝试用超链接替换所有页面上某些文本关键字的第一个实例。我还根据国家/地区代码对这些
我正在使用 JS 打开新页面并将 HTML 代码写入其中,但是当我尝试使用 document.write() 在新页面中编写 JS 时功能不起作用。显然,一旦看到 ,主 JS 就会关闭。用于即将打开的
提问不是为了解决问题,提问是为了更好地理解系统 专家!我知道每当你将 javascript 代码输入 javascript 引擎时,它会立即由 javascript 引擎执行。由于没有看过Engi
我在一个文件夹中有两个 javascript 文件。我想将一个变量的 javascript 文件传递到另一个。我应该使用什么程序? 最佳答案 window.postMessage用于跨文档消息。使
我有一个练习,我需要输入两个输入并检查它们是否都等于一个。 如果是 console.log 正则 console.log false 我试过这样的事情: function isPositive(fir
我正在做一个Web应用程序,计划允许其他网站(客户端)在其页面上嵌入以下javascript: 我的网络应用程序位于 http://example.org 。 我不能假设客户端网站的页面有 JQue
目前我正在使用三个外部 JS 文件。 我喜欢将所有三个 JS 文件合而为一。 尽一切可能。我创建 aio.js 并在 aio.js 中 src="https://code.jquery.com/
我有例如像这样的数组: var myArray = []; var item1 = { start: '08:00', end: '09:30' } var item2 = {
所以我正在制作一个 Chrome 扩展,它使用我制作的一些 TamperMonkey 脚本。我想要一个“主”javascript 文件,您可以在其中包含并执行其他脚本。我很擅长使用以下行将其他 jav
我有 A、B html 和 A、B javascript 文件。 并且,如何将 A JavaScript 中使用的全局变量直接移动到 B JavaScript 中? 示例 JavaScript) va
我需要将以下整个代码放入名为 activate.js 的 JavaScript 中。你能告诉我怎么做吗? var int = new int({ seconds: 30, mark
我已经为我的 .net Web 应用程序创建了母版页 EXAMPLE1.Master。他们的 I 将值存储在 JavaScript 变量中。我想在另一个 JS 文件中检索该变量。 示例1.大师:-
是否有任何库可以用来转换这样的代码: function () { var a = 1; } 像这样的代码: function () { var a = 1; } 在我的浏览器中。因为我在 Gi
我收到语法缺失 ) 错误 $(document).ready(function changeText() { var p = document.getElementById('bidp
我正在制作进度条。它有一个标签。我想调整某个脚本完成的标签。在找到可能的解决方案的一些答案后,我想出了以下脚本。第一个启动并按预期工作。然而,第二个却没有。它出什么问题了?代码如下: HTML:
这里有一个很简单的问题,我简单的头脑无法回答:为什么我在外部库中加载时,下面的匿名和onload函数没有运行?我错过了一些非常非常基本的东西。 Library.js 只有一行:console.log(
我知道 javascript 是一种客户端语言,但如果实际代码中嵌入的 javascript 代码以某种方式与在控制台上运行的代码不同,我会尝试找到答案。让我用一个例子来解释它: 我想创建一个像 Mi
我如何将这个内联 javascript 更改为 Unobtrusive JavaScript? 谢谢! 感谢您的回答,但它不起作用。我的代码是: PHP js文件 document.getElem
我正在寻找将简单的 JavaScript 对象“转储”到动态生成的 JavaScript 源代码中的最优雅的方法。 目的:假设我们有 node.js 服务器生成 HTML。我们在服务器端有一个对象x。
我是一名优秀的程序员,十分优秀!