Fla*_*nix 3 javascript node.js ecmascript-6
我有一个函数负责生成一个随机数并使其可用。
"use strict";
module.exports = function(args) {
let {
min,
max,
} = args;
let currNumber = genRandom(min, max);
const genRandom = (min, max) => Math.floor(Math.random() * max) + min;
const getNumber = () => currNumber;
return Object.freeze({
getNumber
});
};
Run Code Online (Sandbox Code Playgroud)
出于某种我不明白的原因,当我使用 Node.js 7.8 运行此代码时,出现错误genRandom is not defined.
但是,如果我将代码更改为:
let currNumber = genRandom(min, max);
const genRandom = (min, max) => Math.floor(Math.random() * max) + min;
Run Code Online (Sandbox Code Playgroud)
到:
const genRandom = (min, max) => Math.floor(Math.random() * max) + min;
let currNumber = genRandom(min, max);
Run Code Online (Sandbox Code Playgroud)
那么它的工作原理!
我不明白为什么会发生这种情况。我以为const和let像 一样被吊起来var,但这让我相信我错了。
有人可以向我解释这种行为吗?
我认为 const 和 let 就像 var 一样被提升,但这让我相信我错了。
不是真的,let而且const确实是被吊起来的,或者我喜欢称之为半吊。var fooand之间有两个很大的区别let foo:作用域和初始化。您已经知道范围差异。第二个是 with var foo,声明和初始化(with undefined)foo都被提升。随着let,只有声明的foo悬挂,而不是初始化。foo只是初始化时代码的一步一步执行到达let foo陈述。您不能使用(读取或写入)未初始化的标识符。这段不能使用标识符的时间称为临时死区 (TDZ)。
即使使用var,提升的初始化也是使用 的初始化undefined,而不是 右侧的值=:
console.log(typeof foo); // "undefined"
foo(); // TypeError: foo is not a function
var foo = () => {};Run Code Online (Sandbox Code Playgroud)
您所做的更改,getRandom在第一次使用它之前将声明向上移动,是正确的做法。(或者使用函数声明,因为整个声明[包括函数的创建] 都被提升了。)
我们来看看这个半吊的东西:
let foo = "outer";
function x()
{
console.log("...");
let foo = "inner";
console.log(foo);
}
x();Run Code Online (Sandbox Code Playgroud)
(let并且const具有块作用域,但我正在使用一个函数,因为我稍后会进行对比var。)
在 内x,foo直到该let foo行才能使用该内部。但是,你不能访问foo它上面的外部;这失败了:
let foo = "outer";
function x()
{
console.log(foo); // ReferenceError: `foo` is not defined
let foo = "inner";
console.log(foo);
}
x();Run Code Online (Sandbox Code Playgroud)
这就是半提升:内部的声明foo被提升,但变量直到语句才被初始化let foo。这意味着您根本不能foo在该let foo行上方使用(甚至不能从包含范围使用)。在整个函数中,内部foo遮蔽外部foo,但在初始化之前您不能使用它。规范中的Let 和 Const 声明中对此进行了介绍。
这与var:
var foo = "outer";
function x()
{
console.log(foo); // undefined
var foo = "inner";
console.log(foo); // "inner"
}
x();Run Code Online (Sandbox Code Playgroud)
这运行得很好,因为(with )的声明和初始化都被提升到函数的顶部。(提升后,该行变成了一个简单的赋值语句。)因此,内部始终遮蔽外部,并且始终可以访问,最初使用其默认值 ( ) 和后面的 with (一旦分配给它)。fooundefinedvar foo = "inner";foofooundefined"inner"
由于 TDZ 是时间性的(与时间相关),而不是空间性的(与范围内的空间或位置相关),因此您可以使用由let或const(或class)在其声明上方创建的标识符,而不是在其声明之前。这会失败,因为它在初始化之前getNumber尝试访问,而它仍在 TDZ 中:theNumber
const getNumber = () => theNumber;
console.log(getNumber()); // ReferenceError
let theNumber = 42;Run Code Online (Sandbox Code Playgroud)
这是有效的,因为在初始化后getNumber访问:theNumber
const getNumber = () => theNumber;
let theNumber = 42;
console.log(getNumber()); // 42Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1123 次 |
| 最近记录: |