##执行上下文环境
 在一段JS真正运行之前浏览器已经做了一些准备工作:
     1.变量:变量的申明,默认值为undefined;
     2.this:赋值;
     3.函数申明:赋值
 变量:
 console.log(a)  ---> a is not undefined
 console.log(a)-----> undefined    
 var a 
 console.log(a)-----> undefined    
 var a = 10
 this:
 console.log(this)  --->window{top:window,window:wina}
 函数声明:
 console.log(f1);  //functionf1(){}
 function f1(){}    //函数申明
 console.log(f2);   //undefined
 var f2 = function (){}    //函数表达式
 ##函数中的变量
 如果函数中出了以上数据外还有其他数据:
 function fn(x){
     console.log(arguments);                 [10]
     console.log(x);              //----->    10
 }
 fn(10);
 函数每被调用一次,都会产生一个新的执行上下文环境,因为不同的调用可能就会有不同的参数.
 函数在定义的时候就确定了函数内部变量的作用域.
 ##执行上下文栈
 执行全局代码时会产生一个全局上下文环境,每次调用函数时又会产生一个函数上下文环境,当函数调用完成时,这个函数上下文环境以及其中的数据都会被销毁,在重新回到全局上下文环境处于活动状态的执行上下文环境只有一个.实际上,就是一个压栈和出栈的过程.
 var a = 10  //1.进入全局上下文环境
 var fn = function(y){
     var c = 5;
     consolde.log(y + c);
 };
 var bar = function(x){
     var b = 5;
     fn(x + b);   //3.进入函数上下文环境
 };
 bar ();    //2.进入bar函数上下文环境
                                     
 ##作用域和执行上下文
 作用域只是一个“地盘”,一个抽象的概念,其中没有变量,要通过作用域对应的执行上下文环境来获取变量的值,在同一作用域下,不同的调用会产生不同的执行上下文环境,继而产生不同变量的值.
 ##自由变量
 在A作用域中使用的变量x,却没有在A作用域中声明(在其他作用域中声明),对于A作用域来说x是一个自由变量.
 var x = 10;
 function(){
     console.log(x);  //x是自由变量
 }
 ##作用域链
 1.先在当前作用域中查找x,如果有则获取并结束,如果没有则继续;
 2.如果当前作用域是全局作用域,则证明x未定义,结束,否则继续;
 3.(不是全局作用域,就是函数作用域)将创建该函数的作用域作为当前作用域;
 4.跳转到第一步.
转载于:https://www.cnblogs.com/lidongrain/p/4823831.html