javascript:执行环境与做用域链以及函数执行

执行环境定义

定义了变量或者函数有权访问的其余数据,每一个执行环境都有一个与之相关联的变量对象,环境中定义的全部变量和函数都保存在这个对象中。咱们编写的代码没法访问这个对象,但解析器会在处理数据时在后台使用它。
执行环境的建立javascript


全局执行环境

在web浏览器中,全局执行环境被认为是window对象,所以全部全局变量和函数都是做为window对象的属性和方法建立的。代码载入浏览器时,全局执行环境被建立(当咱们关闭网页或者浏览器时全局执行环境才被销毁)。前端

局部执行环境

每一个函数都有本身的执行环境,所以局部执行环境为函数对象。当函数被调用时函数的局部环境被建立(函数内的代码执行完毕后,该环境被销毁,同时保存在其中的全部变量和函数定义也随之被销毁)。java

这个执行环境以及相关的变量对象是个抽象的概念,解释以下web

var a = 1;
function fn(num1,num2){
    var b = 2;
    function fnInner(){
        var c = 3;
        alert(a + b + c);
    }
    fnInner();//fnInner调用时局部执行环境建立
}
fn(4,5);//fn调用时局部执行环境建立

图片描述

图一

做用域链

javascript函数的执行用到了做用域链,这个做用域链是函数定义的时候建立的,当定义一个函数时,它实际保存一个做用域链。当调用这个函数时,它建立一个新的对象来存储它的局部变量,并将这个对象添加至保存的做用域链。做用域链的前端始终都是当前执行的代码所在环境的变量对象。做用域链的末端始终都是全局执行环境的变量对象。做用域链的用途,是保证对执行环境有权访问的全部变量和函数的有权访问浏览器

var scope = 'global scope';
function checkscope(){
    var scope = 'local scope';
    function f(){return scope};
    return f;
}
checkscope()();//local scope

理解:当调用checkscope时,函数f被定义并做为局部变量绑定到了checkscope做用域链上,所以函数f不管在哪里调用,这种绑定依然有效,所以返回值为local scope。函数

var num1 = 1;
function Outer(){
    var num2 = 2;
    console.log(num1 + num2);//3
    function Inner(){
        //这里能够访问num3,num2,num1
        var num3 = 3;
        console.log(num1 + num2 + num3);//6
        }
    //这里能够访问num2,Inner(),num1但不能访问num3
    Inner();
}
Outer();
console.log(num1);//1,执行环境
//这里只能访问num1

做用域链(向上搜索):内部环境能够经过做用域链访问全部的外部环境,但外部环境不能访问内部环境中的任何变量和函数。spa

var name = 'Byron';
    function fn(){
        var name = 'Csper';
        console.log(name);//Casper
    }
    fn();

越往内部的环境,变量权重越高。code

注意:没有带var关键字直接声明的变量属于全局变量如直接声明a = 1,此时的a为全局变量。对象

javscript引擎在进入做用域时,会对代码分两轮处理。第一轮,初始化变量。第二轮,执行代码图片

var a = 1;
function prison (a) {
    console.log(a);//1
    var a;
    console.log(a);//1
}
prison(1);

函数执行

函数调用进入执行环境时,首先处理arguments,初始化形参(默认值为undefined),而后初始化函数内的函数声明,当代码一步一步执行时再初始化函数内的变量声明(进入环境未开始执行代码时,值为undefined)。因此函数内的初始化顺序为变量声明,函数声明,形参。能够从上图图一看出。下面我来举个例子(整个全局环境也是函数)。

alert(typeof fn);//function,函数声明提早
alert(typeof fn0);//undefined,变量声明提早但未赋值
function fn(){
//函数表达式
}
var fn0 = function(){
//函数定义式
}
alert(typeof fn0);//function,此时变量已被赋值
相关文章
相关标签/搜索