JavaScript作用域

当代码在在一个环境中执行时,会创建变量对象的一个作用域链(scope chain),作用域链是用来保证对变量和函数的有序访问。

作用域链的前端,始终是当前执行代码所在的变量对象。作用域链中的下一个变量对象来自外部环境,再下一个变量来自于下一个外部环境,一直延续带全局执行环境。全局执行环境的变量对象始终是作用域链中的最后一个对象。

标识符解析就是沿着作用域链一级一级地搜索标识符的过程。

如例子所示:

var animal = "dog";
function changeAnimal() {
    if (animal == "dog") {
        animal = "cat";
    } else {
        animal = "dog";
    }
}

changeAnimal();

console.log("Now Animal: " + animal);

在例子中,函数 changeAnimal() 的作用域链包含两个对象:它自己的变量对象(其中定义着 arguments 对象)和全局环境的变量对象。可以在函数内部访问 color ,就是因为可以在这个作业域链中找到它。

JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里.

看一下下面这个列子,结果是什么?

function mammals() {
    var kind = "dog";
    var canine = function () {
        console.log("It's a " + kind);
    }
    return canine;
}

function animal(wild) {
    var kind = wild;
    var func = mammals();
    func();
}

animal("wolf");

 当调用 animal 的时候, scope chain是由: {window活动对象(全局)}->{animal的活动对象} 组成.

在刚进入animal函数体时, app的活动对象有一个arguments属性, 俩个值为undefined的属性: kind和func. 和一个值为’wolf’的属性wild;

此时的scope chain如下:

当调用 mammals 的函数体时,此时的 mammals 的 scope chain为:

 注意到, 此时的作用域链中, 并不包含 animal 的活动对象。

在定义 canine 函数的时候, canine 函数的[[scope]]为:

从 mammals 函数返回以后,在体内调用 canine 的时候, 发生了标识符解析, 而此时的sope chain是:

因为scope chain中,并不包含 mammals 活动对象. 所以, kind 标识符解析的结果应该是 mammals 活动对象中的 kind 属性, 也就是 "dog"。

所以运行结果是:

It's a dog
原文地址:https://www.cnblogs.com/zhoufulin/p/4969738.html