功能级别范围和块级别范围之间的差异

时间:2014-02-14 06:29:49

标签: c# javascript function scope

我使用JavaScriptjQuery编程了几个月。我理解闭包并且我已经使用过它们,但是,我仍然无法理解其他语言中的功能级别范围和块级别范围之间的区别 > C#即可。我一直在努力教自己,没有关于这个问题的结果。有人可以用一些简单的例子来解释我吗?

3 个答案:

答案 0 :(得分:13)

在ES6(当前版本的JavaScript)之前,JavaScript只有功能级别范围。即,以下内容:

function foo() {
    console.log('before block: ' + bar);      // prints 'undefined'
    if(true) {
        var bar = 1;
        console.log('inside block: ' + bar);  // prints 1
    }
    console.log('outisde block: ' + bar);     // prints 1
}

完全等同于:

function foo() {
    var bar;
    console.log('before block: ' + bar);      // prints 'undefined'
    if(true) {
        bar = 1;
        console.log('inside block: ' + bar);  // prints 1
    }
    console.log('outisde block: ' + bar);     // prints 1
}

(事实上,我刚刚展示的内容被称为“吊装”,这正是JavaScript所做的:所有变量声明都被提升到函数的顶部;赋值是离开他们所在的地方。)

相比之下,像C#这样的语言有块级别范围。这将导致编译错误:

public void Foo() {
    if(true) {
        var foo = 1;
        Console.WriteLine("inside block: " + foo);
    }
    Console.WriteLine("outside block: " + foo);  // WILL NOT COMPILE
}

但你可以这样:

public void Foo() {
    var foo = 1;
    if(true) {
        foo = 2;
        Console.WriteLine("inside block: " + foo);  // prints 2
    }
    Console.WriteLine("outside block: " + foo);     // prints 2
}

答案 1 :(得分:4)

function scopeTest() {

/* consider this simple for loop
    to be the "block" that we were
    talking about earlier
*/
for (var i = 0; i <= 5; i++)
{
  var inFor = i; 
}

alert(inFor);  // what happens here?

}


// call the function defined above
scopeTest( );

在上面的代码中,我们有一个名为inFor的变量,它在for循环中声明。然后,我们尝试在alert语句中访问for循环之外的inFor变量。

如果上面的代码没有提醒任何内容,那么我们就知道了,因为Javascript使用了块范围。在块作用域语言中,变量inFor在for循环之外是不可见的。这意味着如果Javascript是一个块范围的语言,那么调用&#34; alert(inFor);&#34;将无法识别inFor变量,并且不会将任何内容输出到警告框。

但是,上面的代码实际上输出了一个&#34; 5&#34;,这意味着inFor变量确实存在于for循环之外,这必然意味着Javascript没有块范围。我们的答案是:Javascript没有块范围。

function scopeTest() {

var x = 2;

//this is always true:
if(x == 2)
{
  var y = 15;
  for (var i = 0; i <= 5; i++)
  {
    var inFor = i; 
  }
} 

  console.log(y); // y is defined, prints 15   
  console.log(i);  // i is defined, prints 6
  console.log(inFor);  // inFor is defined, prints 5

}

您可以在上面的代码中看到变量y,i和inFor在if语句内或for循环内声明。但是,即使这些变量是在那些单独的&#34;块&#34;中声明的,它们仍然可以在函数的其余部分中看到。这是因为所有这些变量都在一个函数内声明 - 这就是函数范围的全部内容。

阻止范围与功能范围

因此,如果Javascript没有使用块范围,那么它使用的范围是什么?

好吧,Javascript使用了一个叫做函数范围的东西。

基本上,函数范围和块范围之间的区别在于,在使用函数范围的语言中,函数内声明的任何变量在同一函数内的任何位置都可见。但是对于块作用域,变量的可见性仅限于任何给定的块(无论是if语句,where / for循环等)都由大括号括起来。

http://www.programmerinterview.com/index.php/javascript/javascript-block-scope/ http://www.programmerinterview.com/index.php/javascript/javascript-function-scope/

    {
     here you can't access both a and b
     var a=1
     here you can access only a
        {
        here you can access only a
        var b=3
        here you can access both a and b
        {
        here you can access both a and b
        }
        here too you can access both a and b
        }
        here you can access only a
        }
       here you can't access both a and b

答案 2 :(得分:0)

继续@Ethan Brown 的回答,如果我们使用 let 或 const 而不是 var,我们会得到“referenceError”,因为 letconst > 是块作用域。

function foo() {
    console.log('before block: ' + bar);      // ReferenceError: bar is not defined
    if (true) {
        let bar = 1;                          // bar is not let and not var
        console.log('inside block: ' + bar);  // prints 1
    }
    console.log('outisde block: ' + bar);     // ReferenceError: bar is not defined
}

只是想让答案完整。