javascript之作用域链

作用域链

作用域链是对象的集合,在代码的上下文里,他们提供给标识符进行查找的。

这个规则也很简单,类似于原型链:如果一个变量在它自己的作用域(自己的变量/激活对象)未找到的话,它会继续找它的

父变量对象,依次类推。

对于上下文,标识符有: 变量的名称,函数声明,形参,等等。当一个函数查找它代码的标识符,这个标识符不是本地的变量(

或本地函数,或一个形参),这个变量就就称为自由变量。那么查找这些自由变量就会使用到作用域链。

通常情况下,作用域链是所有的父变量对象的集合,加上(在这个作用域链最前面的)这个函数自身的变量/激活对象。然而,这个

链域可能包含了其他的对象,比如,对象动态的添加到这个作用域链这个上下文执行期间,通过 with--对象,或捕获异常对象。

当去查找某个标识符时,作用域链会从当前的激活对象开始查找,并(如果在自身的激活对象里没找到的话)继续向上查找,重复

下去,同原型链一样。

var x = 10;

(function foo(){
    var y = 20;

    (function bar(){
        var z = 30;
        /*
            x,y 是自由变量,
            在bar的作用域链中,
            他们会被查到在接下
            来的对象(继bar的激
            活对象)
        */
        consloe.log( x + y + z );
    })();
})()

我们将会使用内部属性__parent__来连接作用域对象,这个内部属性会引用到这个作用域链的下个对象。另外一种现实可能是通过数组。

通过__parent__概念,我有下面的图片关于来展现上面的代码(此外,变量对象是存放在函数的[[Scope]]属性的。

在代码执行时,作用域链可以被 with 语句和 catch 语句赋值为对象。尽管这些是简单对象,他们同样有属性(和原型链)。这

会导致这个作用域链查找有两个分支:(1)先看看一个作用域链,(2)在每一个作用域链上—就会进入到这个域链的原型链(

如果这个链域有原型对象)。

Object.prototype.x = 10;

var w = 20;
var y = 30;

console.log( x ); // 10;

(function foo(){
    // "foo" local variables
    var w = 40;
    var x = 100;

    with({z:50}){
        coonsole.log( w, x, y, z ); //40,10,30,50
    }

    console.log( x, w ); // 100, 40

    console.log( window.w ); //20

})();

我们有如下结构图(在我们访问__parent__域链,会先访问 __proto__链。

注意到,不是所有的全局对象实现继承自 Object.prototype。出现这种结果可能是在 SpiderMonkey 引擎里测试的。

直到所有的父变量对象存在,没什么特别的从内部函数获取父数据——我们遍历作用域链去找需要的变量。然而,正如我们上面提到的,

在一个上下文结束,它的所有状态和它自己也被销毁了。同时,一个内部函数可能会从父函数里返回。通常,这个返回的函数会被再次

激活由另一个上下文。带有这个激活对象是否会把这个带有一些自由变量的上下文确实是“销毁”了吗?在普遍的理论上,一个概念有助于

解决这个问题称为闭包,在ECMAScript里这个是直接与作用域链相关的。

时间: 2024-10-12 20:25:23

javascript之作用域链的相关文章

JavaScript的作用域链

问题的提出 首先看一个例子: var name = 'laruence'; function echo() { alert(name); var name = 'eve'; alert(name); alert(age); } echo(); 运行结果是什么呢? 上面的问题, 我相信会有很多人会认为是: laruence eve [脚本出错] 因为会以为在echo中, 第一次alert的时候, 会取到全局变量name的值, 而第二次值被局部变量name覆盖, 所以第二次alert是’eve’.

JavaScript中作用域链和闭包

一.匿名函数 1.1 匿名函数的概念 ? 声明一个没有函数名的函数,就是匿名函数. ? 有函数名的函数就是具名函数. 看下面的代码: <script type="text/javascript"> /* //这里定义了一个函数,而且没有函数名.这样写语法是错误的,如果允许这样定义,那么根本就没有办法调用. //所以,我们可以用一个变量来存储一下 function(){ } */ // 声明了一个匿名函数,并把匿名函数赋值给变量f. 注意这个时候这个匿名函数并没有执行. va

JavaScript系列----作用域链和闭包

1.作用域链 1.1.什么是作用域 谈起作用域链,我们就不得不从作用域开始谈起.因为所谓的作用域链就是由多个作用域组成的.那么, 什么是作用域呢? 1.1.1作用域是一个函数在执行时期的执行环境. 每一个函数在执行的时候都有着其特有的执行环境,ECMAScript标准规定,在javascript中只有函数才拥有作用域.换句话,也就是说,JS中不存在块级作用域.比如下面这样: function getA() { if (false) { var a = 1; } console.log(a); /

理解JavaScript中作用域链的关系

javascript里的关系又多又乱.作用域链是一种单向的链式关系,还算简单清晰:this机制的调用关系,稍微有些复杂:而关于原型,则是prototype.proto和constructor的三角关系.本文先用一张图开宗明义,然后详细解释原型的三角关系 概念 上图中的复杂关系,实际上来源就两行代码 function Foo(){}; var f1 = new Foo; [构造函数] 用来初始化新创建的对象的函数是构造函数.在例子中,Foo()函数是构造函数 [实例对象] 通过构造函数的new操作

javascript函数作用域链 词法作用域

在开发语言中常见的作用域规则有  块级作用域和词法作用域 作用域 顾名思义就是起作用的区域  定义一变量后 ,可以在此范围作用的区域 一.块级作用域就是用一个块结构分割变量的访问区域  块即{ } 代表语言有C 系列语言 二.词法作用域就是变量的作用范围,在书写代码时就已经决定作用的范围,与运行时无关 特点:分割作用域只有函数 变量名提升 函数名提升 函数的声明比变量的声明优先级高 function a(){ } var a; alert(a);//打印出a的函数体 var a; functio

JavaScript.延长作用域链

<!DOCTYPE html> <html> <head> <title>Execution Context Example 3</title> <script type="text/javascript"> function buildUrl() { var qs = "?debug=true"; with(location) { var url = href + qs; } return u

javascript篇-----函数作用域,函数作用域链和声明提前

在一些类似C语言的编程语言中,花括号内的每一段代码都具有各自的作用域,而且变量在声明它们的代码段之外是不可见的(也就是我们不能在代码段外直接访问代码段内声明的变量),我们称之为块级作用域,然而,不同于这类型的编程语言,javascript是没有块级作用域.取而代之的,javascript使用的是块级作用域:变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的. 在如下的所示的代码中,在不同位置定义了变量 i . j 和 k ,它们都在同一个作用域内——这三个变量在函数体内均是有定义

Javascript的作用域、作用域链以及闭包

一.javascript中的作用域 ①全局变量-函数体外部进行声明 ②局部变量-函数体内部进行声明 1)函数级作用域 javascript语言中局部变量不同于C#.Java等高级语言,在这些高级语言内部,采用的块级作用域中会声明新的变量,这些变量不会影响到外部作用域. 而javascript则采用的是函数级作用域,也就是说js创建作用域的单位是函数. 例如: 在C#当中我们写如下代码: static void Main(string[] args) { for (var x = 1; x < 1

JavaScript作用域链详解

JavaScript的作用域链还是很有味道的,搞懂了这个知识点,闭包的问题也就迎刃而解咯 1.JavaScript的全局变量和局部变量 首先,先来看看js的全局变量和局部变量,js不是块级作用域,所以不能把你学过的C/C++作用域的知识用在js中! (1)全局变量 js的全局变量也可以看做window对象的属性,这句话怎么理解,请看以下代码: var x = 10; alert(window.x);//弹出10 也就是说var x = 10;等价于window.x=10; 再来看一段代码 fun