Javascript 为什么在函数中创建同名变量时函数参数没有被覆盖?

Javascript 为什么在函数中创建同名变量时函数参数没有被覆盖?,javascript,variables,function-parameter,Javascript,Variables,Function Parameter,Javascript是功能范围语言,对吗?当我在函数内部声明一个新变量,该变量使用与函数参数相同的名称时,为什么新定义的变量仍然与参数保持相同的数据 我认为它应该是未定义的?var a实际上是一个变量声明语句。定义函数时,函数中声明的所有变量都会在代码执行之前进行处理,因此您甚至可以在运行时执行实际声明行之前使用这些变量。这就是所谓的。所以,不管你声明一个变量多少次,这个变量实际上只声明一次 在本例中,您已将a定义为函数的参数之一,其作用域为当前函数。然后声明一个同名的变量。由于函数中已经声明了

Javascript是功能范围语言,对吗?当我在函数内部声明一个新变量,该变量使用与函数参数相同的名称时,为什么新定义的变量仍然与参数保持相同的数据


我认为它应该是未定义的?

var a
实际上是一个变量声明语句。定义函数时,函数中声明的所有变量都会在代码执行之前进行处理,因此您甚至可以在运行时执行实际声明行之前使用这些变量。这就是所谓的。所以,不管你声明一个变量多少次,这个变量实际上只声明一次

在本例中,您已将
a
定义为函数的参数之一,其作用域为当前函数。然后声明一个同名的变量。由于函数中已经声明了
a
,因此作为参数之一,
var a声明将被忽略

这就是为什么控制台中会出现
为什么未定义?

而不是
var a,假设您有
var a=1
,在这种情况下,变量已声明,但赋值表达式将在运行时求值,值
1
将赋值给
a
。因此,
console.log
将打印
1


ECMA脚本5.1规范中的第节对该行为进行了解释

  • 如果代码是功能代码,则

    a。设func是其[[Call]]内部方法启动代码执行的函数。让名称为func的值 [[FormalParameters]]内部属性

    b。设argCount为args中的元素数

    c。设n为数字0

    d。对于名称中的每个字符串argName,请按列表顺序执行

    一,。设n为n加1的当前值

    二,。如果n大于argCount,则让v未定义,否则让v为args的第n个元素的值

    iii.让argalreadydecared成为调用env的HasBinding具体方法并将argName作为参数的结果。

    iv.如果argalreadydecared为false,则调用env的CreateMutableBinding具体方法,将argName作为 参数。

    五,。调用env的SetMutableBinding具体方法,将argName、v和strict作为参数传递

  • 对于代码中的每个VariableDeclaration和VariableDeclarationNoIn d,按源文本顺序执行

    a。设dn为d中的标识符

    b。让varalreadydecared成为调用env的HasBinding具体方法并将dn作为参数传递的结果

    c如果varalreadydecared为false,则

    一,调用env的CreateMutableBinding具体方法,将dn和configurableBindings作为参数传递。

    二,。调用env的SetMutableBinding具体方法,将dn、undefined和strict作为参数传递

  • 正如我们在规范中看到的,函数中声明的参数和变量实际上都是在与定义它们的函数对应的执行环境中定义的。因此,如果参数和变量具有相同的名称,那么实际上只定义一次变量,而忽略第二个声明

  • 您正在将变量a作为参数传递给函数检查。
    函数检查范围(a){

  • 在函数中,您再次尝试声明var a,
    var a;

  • 这两个都在同一范围内,对吗?即都在函数check()内

    根据,函数中的
    var a
    是作为参数传递的同一个变量,您只是在声明之前使用它……您可以用JS来实现

    因此,您编写的代码与

    var a = 'why is this not undefined?';
    function checkScope(a) {
        var a;
        console.log(a);
    }
    checkScope(a);
    
    i、 只是忽略了var a

    您希望var a返回undefined,那么代码是这样的

    var a = 'why is this not undefined?';
    function checkScope(a) {
    
        console.log(a);
    }
    checkScope(a);
    

    这次我们没有将参数a传递给函数,并且在函数范围内创建了一个新变量
    var a
    ,因此变得未定义,因为JavaScript忽略了变量的重新声明。但是,如果改为:

    var a = 'why is this not undefined?';
    function checkScope() {
       var a
        console.log(a);
    }
    checkScope();
    
    a
    的值将被覆盖。因为
    var a='foo';
    由变量声明(
    var a;
    )和值赋值(
    a='foo';
    )组成


    此行为在中进行了描述。

    参数仍在函数中定义,因为当变量已在同一范围内定义时,
    var a;
    将被忽略

    var A;
    这样的语句并不意味着变量是在代码中的该点创建的。所有变量声明都位于作用域的顶部,因此您可以在作用域中多次重新声明它们,并且它们仍然只创建一次

    但是,如果一个声明有赋值,比如
    var a=2;
    ,则赋值发生在语句位于代码中的位置,而不管该声明是否被忽略

    例如:

    功能检查(a){
    //a和b都存在于这里
    document.write('a='+a+',b='+b+'
    '); var b=1; document.write('a='+a+',b='+b+'
    '); var a=2;//未重新创建,但已分配 document.write('a='+a+',b='+b+'
    '); }
    勾选(42);
    我不确定,但我认为,由于提升,两个
    a
    变量都是在调用函数之前声明的,因此参数
    a
    与函数中声明的
    a
    变为相同的变量。什么是“函数范围”?JS有函数范围,即参数名称、函数和va
    var a = 'why is this not undefined?';
    function checkScope(a) {
        var a = 'foo';
        console.log(a);
    }
    checkScope(a);