为什么这个JavaScript命名的函数表达式会抛出带有var的异常,而不是没有var的异常 var foo=功能条(i){ bar=“更改条参照”; 如果(i

为什么这个JavaScript命名的函数表达式会抛出带有var的异常,而不是没有var的异常 var foo=功能条(i){ bar=“更改条参照”; 如果(i,javascript,Javascript,上述函数没有错误 var foo = function bar(i) { bar = "change bar reference"; if (i < 5) { setTimeout(function () { console.log(i); bar(++i); }, 1000 ); } } var foo=功能条(i){ var bar=“更改条

上述函数没有错误

var foo = function bar(i) {
    bar = "change bar reference";
    if (i < 5) {
        setTimeout(function () {
            console.log(i);
            bar(++i);
        },
            1000
        );
    }
}
var foo=功能条(i){
var bar=“更改条引用”;
如果(i<5){
setTimeout(函数(){
控制台日志(i);
bar(++i);
},
1000
);
}
}
var
添加到条后,第二个函数出现错误

我希望这两个函数都会抛出异常,而不仅仅是带有
var bar
的第二个函数

我不明白为什么只有第二个函数抛出异常

我发现带有
var
的变量声明不会覆盖标识符“bar”,但赋值将在运行时完成。我理解为什么var bar是一个字符串而不是第二个函数上的函数,因此会抛出一个异常

为什么第一个函数不抛出异常? 条形图清楚地指定给字符串

我读了这本书,从下面得到了一些可能有用的东西

FunctionExpression中的标识符可以从FunctionExpression的FunctionBody内部引用,以允许函数递归调用自身。但是,与FunctionDeclaration不同,FunctionExpression中的标识符不能从中引用,也不会影响包含FunctionExpression的范围

“FunctionExpression中的标识符不能从中引用”是否表示我不能执行
bar=“更改条引用”在第一个函数中

当JavaScript脚本引擎看到
bar=“change bar reference”
时,它会做什么?它只是跳过了这一行吗

编辑:未捕获类型错误:bar不是函数


foo(1)

至少在调用
foo
bar
时,会出现一个错误,因为该函数不再存在

为什么第一个函数不抛出异常?条形图清楚地指定给字符串

在运行时,如果不调用函数,什么也不会发生,但是在调用函数之后,变量
bar
有一个字符串作为值,而不是用于进一步调用超时的函数

视情况而定。在Edge上,它只是跳过赋值,在Chrome上,它抛出一个错误

var foo = function bar(i) {
    var bar = "change bar reference";
    if (i < 5) {
        setTimeout(function () {
            console.log(i);
            bar(++i);
        },
            1000
        );
    }
}
这意味着命名函数被实现为常量


var foo=function bar(i){/这样做的原因是,根据ES规范,命名函数的名称上有一个不可变的绑定:

发件人:

  • 让envRec成为funcEnv的EnvironmentRecord
  • 让name为BindingIdentifier的StringValue
  • 执行envRec.CreateImmutableBinding(名称)
  • 不可变绑定意味着无法覆盖标识符的值。此外,尝试在严格模式下为其赋值:

    12.14.1:在ECMAScript 2015中,包含对不可变绑定(如FunctionExpression的函数名)赋值的严格模式代码不会产生早期错误。相反,它会产生运行时错误

    注意:

    var foo=功能条(){
    bar=2;
    控制台日志(bar);
    };
    
    foo();
    让我试着用简单的词来阐述。 在第一个函数中,您试图修改/重新定义/覆盖NFE(命名函数表达式)“bar”,这是不允许的。因为您没有使用“严格模式”,所以您没有收到运行时错误。如果您将在严格模式下,您将收到“未捕获类型错误:分配给常量变量”因为在NFE内部,函数名被视为常量,所以没有人可以重写它的值

    在第二个函数中,“bar”将推断一个字符串值,这就是它抛出错误的原因,因为在几行之后,您将它用作函数。 我希望,这有点道理。 要进行双重检查,我们可以执行以下脚本: 下面的脚本将返回“function”,然后返回“bar”函数的定义,因为我并没有使用严格模式

    Assignment to constant variable.
    

    究竟什么是“例外”是这样吗?您正在将函数
    bar
    更改为字符串,这就是您看到错误的原因。第一个,您在全局范围内设置了
    bar
    ,但是您在局部范围内也有
    bar
    ,这将首先被看到。在第二个,您将在局部范围内创建这两个。如果您将第一个更改为
    window.bar
    您所做的事情将变得更加明显。@Pointy Uncaught TypeError:bar不是函数。@Keith我很确定第一个函数在全局范围内没有
    bar
    bar
    是命名函数表达式的标识符,它只能在函数内部访问。这就是为什么这个问题很有趣。对不起,我有一些拼写错误。请尝试再次复制和粘贴。应该可以。foo(1)命名函数表达式只有在函数中没有变量声明且标识符与我刚才发现的相同时才是常量。如果您查看第二个函数,其中有
    var bar
    ,则
    bar
    的行为类似于常规变量。我的所有测试都在chrome上进行。但在第二个函数中,它使用带有字符串的bar作为函数,它抛出一个错误。这两个函数都试图将
    bar
    更改为字符串。只有一个函数成功,因为另一个是常量。这两个函数都是相同的,除了一个函数有一个额外的
    var
    。我怀疑对
    bar
    的赋值确实有影响,即隐式创建了一个global
    bar
    。如果函数处于“严格”模式,则可能会引发错误。@Pointy我以为它也会创建全局变量,但它没有。将其作为严格模式运行,它会给我“TypeError:赋值给常量变量”。因此我猜bar
    var foo = function bar() {
    console.log(typeof(bar)) ;
    bar = "new definition"; // try to redefine
    console.log( bar ); 
    };