有人能解释一下为什么它被创建了吗?
它引发ReferenceError或SyntaxError而不是返回undefined的逻辑是什么? ReferenceError:
console.log(typeof foo);
let foo;
语法错误:
let foo;
let foo;
未定义:
console.log(typeof foo);
console.log(typeof foo);
let foo;
语法错误:
let foo;
let foo;
未定义:
console.log(typeof foo);
在初始化变量之前使用它是一个错误,这种错误应该被视为一种错误类型,因为它可以帮助开发人员注意到他们的错误并进行修正。变量的行为从undefined
开始已经引起了太多的问题,如果类似的语义用于const
变量或静态类型注释,问题将会更加严重。
__proto__
)可能是可能的,但不值得; 而且仍有许多合理的使用场景,例如在全局范围内使用 var
(TDZ不是它们唯一的区别)。关于 for each
,它从未成为标准(由于ES4失败了),而只是 Mozilla 的一个实验性扩展。 - Bergivar
不属于这些。 - Bergi!
比使用 typeof
检查更省击键次数。因此,唯一的理由就是如果你需要练习打字,并且在输入完成后将删除代码。 - Chris Baker变量一旦被定义就应该存在,这是有道理的。由于来自外部作用域的变量在嵌套作用域中可以访问,因此以下代码非常令人困惑:
var foo = 'out';
function bar () {
foo = 'in';
console.log(foo);
var foo;
}
bar();
bar()
是干什么的?它创建了一个名为 foo 的新变量,并将 'in'
赋值给它,然后在控制台中显示它。之后,来自外部作用域的变量仍然等于'out'
。因此,在使用变量之前定义它们是更明智的选择。我相信,你可以在声明变量之前使用变量只是出于实现简单和效率的考虑,但这只是我的大胆猜测。
然而,在 JavaScript 中,使用 var
关键字创建的变量只能从它们的函数中访问,而不能从它们的块中访问。这允许使用更宽松的语法,如下例:
function setGameMode (mode) {
if (mode === 'peaceful') {
var count = 0;
for (var i = 0; i < mobs.length; ++i) {
if (mobs[i] instanceOf EvilMob) {
mobs[i].despawn();
++count;
}
}
console.log('Removed ' + count+ ' evil mobs out of ' + i);
mobSpawner.evil = false;
} else if (mode ==='chaotic') {
var count = 0;
for (var i = 0; i < mobs.length; ++i) {
if (mobs[i] instanceOf NiceMob) {
mobs[i].despawn();
++count;
}
}
console.log('Removed ' + count + ' nice mobs out of ' + i);
mobSpawner.nice = false;
}
}
i
变量在for循环后仍然存在,这要归功于函数作用域变量。这也是为什么var
关键字允许您定义变量两次的原因。如果您被迫只写一次var
,那将不太实用。对于let
变量,这种“宽松”的特性变得无用,因为这些变量应该尽快释放。i
在if块内部,无法确定是否需要使用它,除非实际运行代码。但是,由于JS具有函数作用域变量,它必须从函数开始就创建变量。对于let
变量来说,这样做是没有必要的。typeof someundefinedvar
返回“undefined”的原因,那是因为您需要一种检查可能已在外部范围中声明的变量的方法。但是,对于块级作用域的变量,您不需要该功能。let
变量应该立即使用并丢弃。var foo;
导致了奇怪的问题。但我不认为它应该表现出这种方式,看起来像是一个 bug。 - user7393973var foo
在函数内创建了局部变量foo,它遮蔽了外部的foo。最好避免使用这样的代码,它很糟糕^^ - Dominovar foo = 'out';
创建了一个全局变量(至少对于其他代码来说是这样)。然后在函数内部,foo = 'in';
改变了它的值。var foo;
应该只是声明了一个本地(函数作用域)变量。 - user7393973console.log(typeof a);
let a;
在上述语句中,您没有定义变量a
而是使用它。在JavaScript中,定义变量是必要的。该变量是您值的引用,因此会显示未定义的引用错误。
let a;
let a;
在第二个语句中,您定义了一个变量两次。js不允许您在同一块作用域中定义任何变量超过一次。
console.log(typeof foo);
在第3个语句中,由于第一个函数显示变量未定义的错误。默认情况下,它未定义。您可以使用未定义的变量。
var
,但不能使用let
。你没有解释为什么情况3与情况1不同。 - Domino如果您查看您在问题中提供的那些异常的文档,您可以看到其中的原因,我认为这里没有讨论。
首先要注意的是,直到第3版才出现EMCAScript中的异常。var显然比这个语言特性早很多。为什么var和let不同主要是由于在引入let时已经可用异常,而在引入var时不可用异常。这段历史强调了所有这些内容。1999年也很忙碌!
无论如何,进入齿轮。看看这里发生了什么:
// example A
(function () {
console.log(somethingUndefined - 1);
var somethingUndefined;
console.log('another operation');
})();
出现错误,然后代码继续执行。我们能捕捉到它并处理吗?
// example B
(function () {
try {
console.log(somethingUndefined - 1);
var somethingUndefined = 50;
console.log('another operation');
} catch (e) {
console.log('I want to deal with problems here');
return;
}
console.log('plowing on');
})();
不行。
幕后,这段代码看起来像这样:
// example C
(function () {
var somethingUndefined = undefined;
try {
console.log(somethingUndefined - 1);
somethingUndefined = 50;
console.log('another operation');
} catch (e) {
console.log('I want to deal with problems here');
return;
}
console.log('plowing on');
})();
不存在“暂时性死区”,因为在示例B和C中,变量 somethingUndefined
从未不是某个值。它是一种typeof“undefined”, somethingUndefined === undefined
,但这并不意味着没有任何值。然后它的值为50,但太晚了,已经没用了。无论有用与否,我们都可以使用它来完成任务,因为它有一个值。在第1行和第8行,它始终有一些值。在此处比较输出上的差异:
// example D
(function () {
try {
console.log(somethingUndeclared - 1);
console.log('another operation');
} catch (e) {
console.log('I want to deal with problems here');
console.log(e);
}
})();
somethingUndeclared
在任何时候都是不存在的。它始终处于死区状态。我不确定以上代码从哪个 EMCAScript 版本开始引发异常,但它这样做会更好,因为这种情况永远是错误的。somethingUndeclared
,可能是为了其他目的。或者代码 var somethingUndeclared;
在作用域或父级作用域中某个地方闲置着,所以在上述代码中没有抛出任何异常。这就是几乎完全使用 let 或 const 的理由。undefined
,它是一个等待发生异常的例外。在到达 let 语句之前,它的行为类似于未声明的变量,会抛出异常,然后在声明行上,它的行为类似于带有值的 var。它是 var 行为和未声明变量结果的混合体。
// example D
(function () { // temporal dead zone, something is nothing
try { // temporal dead zone, something is nothing
console.log(something - 1); // exceptional behavior! temporal dead zone
let something = 50; // temporal live zone begins here!
console.log('another operation');
} catch (e) {
console.log('I want to deal with problems here'); // you could call this a dead zone
console.log(e); // dead
}
// dead
})(); // way dead
undefined = 100;
将会是一场灾难时,我们可以选择使用异常处理。当渐进增强失败并且我们没有工具提示时,我们的用户体验就不如我们希望的那样好。var和let有着不同的历史和不同的负担,所以它们很可能会一直表现不同。