javascript中变量的范围是什么?它们在函数内部的作用域与在函数外部的作用域相同吗?或者这有关系吗?此外,如果变量是全局定义的,那么变量存储在哪里?


当前回答

ES5及更早版本:

Javascript中的变量最初(在ES6之前)是函数范围的。词汇范围这一术语意味着您可以通过“查看”代码来查看变量的范围。

用var关键字声明的每个变量都在函数的作用域内。但是,如果在该函数中声明了其他函数,则这些函数将可以访问外部函数的变量。这称为作用域链。其工作方式如下:

当一个函数试图解析一个变量值时,它首先查看自己的范围。这是函数体,即花括号{}之间的所有内容(除了在此范围内的其他函数内的变量)。如果它在函数体中找不到变量,它将爬上链,查看函数中定义函数的变量范围。这就是词法作用域的含义,我们可以在代码中看到这个函数的定义,因此可以通过查看代码来确定作用域链。

例子:

//全局范围var foo=“全局”;var bar=“全局”;var foobar=“全局”;函数outerFunc(){//outerFunc范围var foo='outerFunc';var foobar='outerFunc';innerFunc();函数innerFunc(){//innerFunc范围var foo='innerFunc';console.log(foo);console.log(bar);console.log(foobar);}}outerFunc();

当我们试图将变量foo、bar和foobar记录到控制台时,会发生以下情况:

我们尝试将foo记录到控制台,foo可以在函数innerFunc本身中找到。因此,foo的值被解析为字符串innerFunc。我们试图将bar记录到控制台,但在函数innerFunc本身中找不到bar。因此,我们需要攀登范围链。我们首先查看定义了函数innerFunc的外部函数。这是outerFunc函数。在outerFunc的作用域中,我们可以找到变量栏,其中包含字符串“outerFun”。在innerFunc中找不到foobar。因此,我们需要将作用域链升级到innerFunc作用域。在这里也找不到它,我们爬到了另一个层次的全局范围(即最外面的范围)。我们在这里找到了保存字符串“global”的变量foobar。如果在攀爬范围链之后没有找到变量,JS引擎将抛出referenceError。

ES6(ES 2015)及以上版本:

词汇范围和范围的概念仍然适用于ES6。然而,引入了一种声明变量的新方法。具体如下:

let:创建块范围变量const:创建一个必须初始化且不能重新分配的块范围变量

var和let/cont之间最大的区别是var是函数范围的,而let/cont是块范围的。下面是一个例子来说明这一点:

let letVar=“全局”;var varVar=“全局”;函数foo(){if(真){//用let声明的这个变量的作用域是if块,块作用域设letVar=5;//用let声明的这个变量的作用域是函数块,函数作用域var varVar=10;}console.log(letVar);console.log(varVar);}foo();

在上面的示例中,letVar记录全局值,因为用let声明的变量是块范围的。它们不再存在于各自的块之外,因此无法在if块之外访问变量。

其他回答

我的理解是有三个范围:全球范围,全球可用;局部范围,无论块如何,整个功能都可用;和块范围,仅对使用它的块、语句或表达式可用。全局和局部作用域用关键字“var”表示,无论是在函数内还是在函数外,块作用域都用关键字“let”表示。

对于那些认为只有全局和局部范围的人,请解释为什么Mozilla会有一个完整的页面来描述JS中块范围的细微差别。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

我发现许多新接触JavaScript的人很难理解继承在默认情况下在语言中是可用的,而函数作用域是迄今为止唯一的作用域。我为去年年底我写的一个名为JSprety的美化者提供了一个扩展。功能为代码中的函数范围着色,并始终将颜色与该范围中声明的所有变量相关联。当在不同的范围中使用来自一个范围的颜色的变量时,可以直观地演示闭包。

尝试以下功能:

http://prettydiff.com/jspretty.xhtml?c=white&jsscope

观看演示:

http://prettydiff.com/jspretty.xhtml?c=white&jsscope&s=http://prettydiff.com/lib/markup_beauty.js

在以下位置查看代码:

http://prettydiff.com/lib/jspretty.jshttps://github.com/austincheney/Pretty-Diff/blob/master/lib/jspretty.js

目前,该功能支持深度为16个嵌套函数,但目前不为全局变量着色。

在JavaScript中,有两种类型的作用域:

本地范围全局范围

Below函数有一个局部范围变量carName。这个变量不能从函数外部访问。

function myFunction() {
    var carName = "Volvo";
    alert(carName);
    // code here can use carName
}

Below Class有一个全局范围变量carName。这个变量可以从类中的任何地方访问。

class {

    var carName = " Volvo";

    // code here can use carName

    function myFunction() {
        alert(carName);
        // code here can use carName 
    }
}

全球范围:

全球变量就像全球明星(成龙、纳尔逊·曼德拉)。您可以从应用程序的任何部分访问它们(获取或设置值)。全球功能就像全球活动(新年、圣诞节)。您可以从应用程序的任何部分执行(调用)它们。

//global variable
var a = 2;

//global function
function b(){
   console.log(a);  //access global variable
}

本地范围:

如果你在美国,你可能会认识金·卡戴珊(Kim Kardashian),她是臭名昭著的名人(她以某种方式制作了小报)。但美国以外的人不会认出她。她是当地的明星,与她的领地息息相关。

局部变量就像局部恒星。您只能在范围内访问它们(获取或设置值)。本地函数就像本地事件一样,只能在该范围内执行(庆祝)。如果您想从作用域之外访问它们,将出现引用错误

function b(){
   var d = 21; //local variable
   console.log(d);

   function dog(){  console.log(a); }
     dog(); //execute local function
}

 console.log(d); //ReferenceError: dddddd is not defined    

查看本文以深入了解范围

ECMAScript 6引入了let和const关键字。这些关键字可以用来代替var关键字。与var关键字相反,let和const关键字支持在块语句中声明局部范围。

var x = 10
let y = 10
const z = 10
{
  x = 20
  let y = 20
  const z = 20
  {
    x = 30
    // x is in the global scope because of the 'var' keyword
    let y = 30
    // y is in the local scope because of the 'let' keyword
    const z = 30
    // z is in the local scope because of the 'const' keyword
    console.log(x) // 30
    console.log(y) // 30
    console.log(z) // 30
  }
  console.log(x) // 30
  console.log(y) // 20
  console.log(z) // 20
}

console.log(x) // 30
console.log(y) // 10
console.log(z) // 10