javascript 功能级作用域与块级作用域的区别

4zcjmb1e  于 2022-12-25  发布在  Java
关注(0)|答案(3)|浏览(85)

我用JavaScript编程已经有几个月了,大部分时间都在使用jQuery。我理解闭包,我也使用过它们,但是,我仍然不明白在其他语言中,如**C#**中,函数级作用域和块级作用域之间的 * 区别 * 是什么。我一直在努力自学,但没有结果。谁能举几个简单的例子给我解释一下?

9njqaruj

9njqaruj1#

在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
}

(As事实上,我刚才展示的东西叫做“提升”,这正是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
}
zf9nrax1

zf9nrax12#

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( );

在上面的代码中,我们在for循环中声明了一个名为inFor的变量,然后我们尝试在alert语句中访问for循环之外的inFor变量。
如果上面的代码没有提示任何东西,那么我们知道这是因为Javascript使用了块作用域。在块作用域语言中,变量inFor在for循环之外是不可见的。这意味着如果Javascript是块作用域语言,那么对"alert(inFor); "将无法识别inFor变量,并且不会向警报框输出任何内容。
但是,上面的代码实际上输出了一个"5",这意味着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循环中声明。但是,即使这些变量是在那些单独的"块"中声明的,它们仍然对函数的其余部分可见。这是因为所有这些变量都是在一个函数中声明的--这就是函数作用域的意义所在。

    • 块作用域与函数作用域**

那么,如果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
yb3bgrhw

yb3bgrhw3#

继续@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
}

只是想让答案完整。

相关问题