JavaScript特性二:执行环境与作用域链

来源:互联网 发布:ios下载软件 编辑:程序博客网 时间:2024/06/05 11:42

JavaScript特性一:变量作用域

JavaScript特性二:执行环境与作用域链

JavaScript特性三:this关键字

首先来看下全局变量和局部变量

全局变量

JavaScript解析器开始运行时,首先要做的事情之一就是在执行任何代码之前创建一个全局对象

这个对象的属性就是JavaScript程序的全局变量,当声明一个JavaScript全局变量时,实际上是定义了该全局对象的一个属性

var a = 1;  console.log(this.a);//1console.log(window.a);//1

 

局部变量

局部变量也是一个对象的属性,这个对象被称为调用对象(该对象无法编码访问,但解析器会使用该对象

在执行一个函数时,函数的参数和局部变量是作为调用对象的属性而存储的

每个函数都用一个完全独立的对象来存储局部变量,这样可以避免一函数的局部变量的值被另一函数的同名局部变量的值所覆盖

 

执行环境

执行环境就是JavaScript代码段执行时所在的环境,每个执行环境都有一个与之关联的对象

对不属于任何函数的JavaScript代码来说,该对象为全局对象;对函数来说,该对象为其调用对象

JavaScript的解释器每次开始执行一个函数时,都会为那个函数创建一个执行环境,所有JavaScript函数都运行在自己独有的执行环境中,并且拥有自己的调用对象

 

作用域链

之前讨论变量的作用域时,我们只是基于JavaScript的词法结构来定义它们,即全局变量具有全局作用域,函数中声明的变量具有局部作用域

现在我们知道全局变量是全局对象的属性,而局部变量是一个特殊的调用对象的属性,那么我们就可以再次关注一下变量作用域的表示方法,对它进行再定义,这个新的定义就是作用域链,它为JavaScript的工作过程提供了一种强大的、新的理解

每个JavaScript执行环境都有一个和它关联在一起的作用域链,这个作用域链是一个对象链,链中保存着全局对象或调用对象,对象中保存着全局变量或局部变量

当查找特定变量的值时,总是从作用域链头部的对象开始搜索,如果对象中包含查找的变量,则返回该变量的值,否则搜索下一个对象,直到链尾,如果在链尾的对象中还没找到,则该对象为未定义对象,抛出异常

我们来看下边这段代码

var a = 'global';function outside(){    var b = 'outside';    function inside(){        var c = 'inside';        console.log(a);//global    }    inside();}outside();

对于不属于任何函数定义的代码,其作用域链只包含一个对象:全局对象

对于outside函数,其作用域链包含2个对象:outside函数的调用对象 -> 全局对象

对于inside函数,其作用域链包含3个对象:inside函数的调用对象 -> outside函数的调用对象 -> 全局对象

当查找局部变量a时,首先查看inside函数调用对象,没有找到;接着查看outside函数调用对象,也无法找到;最后查看全局对象,发现全局对象包含一个名为a的属性,返回该属性的值

再看一段代码

var a = 'global';function f1(){   console.log(a);}function f2(){   var a = 'f2';   f1();}f2();//global

输出结果是global而不是f2,因为作用域链(也就是函数作用域)是在定义时确定的,而不是在调用时确定的

函数f1的作用域链是:f1函数的调用对象 -> 全局对象

0 0