关于JS中作用域的一些理解

来源:互联网 发布:matlab 数据拟合 编辑:程序博客网 时间:2024/06/09 07:57

所谓的作用域,一句话概括就是:变量在声明它们的函数体以及这个函数体内嵌套任何的函数体内都是有定义的。

由于函数本身也是一个变量,所以它也有作用域,函数的作用域和变量的作用域一样,也是声明其定义时所在的作用域,与运行时无关,即函数的作用域在函数体内的变量声明之前就可用了。

JS不像其他语言,在JS中,ifwhilefor等代码块是不能形成独立的块级作用域,所谓的块级作用域是指一对花括号里面的每一段代码都有独立的作用域,外界是访问不到的,但JS并不是,在JS中,同一个函数体内,如果里面含有ifwhilefor等语句,那么函数体内的变量是可以访问到这些语句里面的,但是在这个函数的外部却是访问不到函数内部的变量的,此时变量又分为全局变量和局部变量:

全局变量:全局变量是指整个程序的任意一行都可以引用的变量。由于它的作用域是整个程序,所以又称为全局变量作用域。

局部变量:局部变量是指定义在函数内部的变量。由于它的作用域是局部性的,所以又称为局部变量作用域。

JavaScript中,函数内部可以直接读取全局变量,而函数外部是无法直接读取函数内部的局部变量的。

1

var a=1;

function f1(){

    console.log(a);

}f1();

输出结果为:1

 

2

function f2(){

          var a=1;

}

console.log(a);

输出结果为:”a is notdefined”。(即a未定义,这是为什么呢?这是因为此时是在函数外面,所以是无法访问函数内部的局部变量a的)

 

3

function f3(){

      a=1;

      console.log(a);

}f3();

输出结果为:1

(为什么例3中的结果为1?因为没有对a进行var声明,所以它是一个全局变量,所以即便它是在函数内部,在函数外部也是能读取它!)

 

变量提升:在提到变量作用域时,有一个词不得不提一下,那就是变量提升,什么是变量提升呢?举个例子:

例:

var a=1

function test(){

console,log(a);

}test();

通过前面的了解,我们都知道这个例子运行的结果是1.

Ok,那么再举个例子:

var a=1;

function test(){

  console.log(a);

var a=2;

}test();

那这个例子的运行结果是什么呢?答案是undefined。这是为什么呢?这就是上面提到的变量提升,其实上面的例子运行的过程这样的:

var a=1;

function test(){

  var a

  console.log(a);

a=2;

}test();

所以才会undefined。也就是说,函数中变量的作用域是在函数定义时确定的,也就是在预处理过程中完成的,而变量的值是在函数调用的时候才确定下来的,test()在运行时只会去确认它的值,所以要区分好函数的定义和调用,两者是不一样的函数执行时候的环境是定义时的作用域,而不是调用时所在的作用域。

 

 

执行环境:首先需要注意一点的是,执行环境和作用域是两个完全不同的概念。

执行环境也称执行上下文,函数每次调用都有与之紧密相关的作用域和执行环境,从根本上说,作用域是基于函数的,而执行环境是基于对象的。作用域涉及到所被调用的变量访问,并且不同的调用场景是不一样的。而对于执行环境而言,每个执行环境都有一个与之相关联的变量对象,环境中所有定义的变量和函数都保持在这个对象当中,执行环境用于当前所执行代码的对象的引用。

执行环境分为创建和执行两个阶段,在创建阶段,解析器首先会创建一个变量对象,它由定义在函数中的声变量、函数声明以及参数组成。然后在执行阶段进行代码的执行。

我们可以通过解析器工作的过程去更好的理解执行环境:当JS代码被浏览器载入时,默认最先进入的是一个全局的环境,当在全局环境中调用一个函数时,程序流就会进入到该函数内,此时JS引擎就会为该函数创建一个新的执行环境(可以理解为局部执行环境),并且将其压入到执行环境堆栈的顶部。由于浏览器总是会执行当前堆栈顶部的执行环境,一旦执行完毕,该执行环境就会被弹出,然后进入其下的执行环境执行代码,这样,堆栈中的执行环境就会依次被执行并且弹出堆栈,直到回到全局的执行环境。

0 0
原创粉丝点击