什么是执行环境?

  我想了很长时间,实在是无法组织合适的语言来解释执行环境 这个概念;

  就是你的JS代码在浏览器这个宿主对象的环境中执行的上下文环境;

  这么说吧,你在写代码的时候,定义了一个函数,那你这个函数有执行环境吗?肯定是没有执行环境的;

  只有当你把代码放到浏览器中,或者是Chrome的V8引擎上,调用这个函数,这个时候函数的执行环境才会出现;

  希望你知道中文里:全局、和局部是什么意思;

  天气预报中说:今天全国有雨,视中国这960万平方公里为全局,说上海地区有雨,就是视上海为中国的一个局部,就是局部地区有雨;

  这样就好说了,函数在调用的时候产生的一个执行环境就是一个局部环境,那么对应的,一定有一个全局的执行环境;

  JS是一门脚本语言,是一门解释型语言,也就是说,它无法直接编译成可执行代码,所以说,JS代码想要执行,就必须有一个宿主;

  在客户端中,JS应用的地方一般是浏览器,所以浏览器就是JS的一种宿主;

  而全局执行环境就是这个宿主环境;

  前面说的,函数执行的时候有一个自己的执行环境,当函数执行完毕,函数的执行环境也就销毁了,函数内部的属性/方法也就随风飘散了;

  而全局执行环境,在浏览器关闭的时候(退出应用),这个全局执行环境才会销毁;

什么是作用域?

  作用域就是你的一段JS代码中变量的使用、访问、被访问的范围;

  作用域只有两种:全局作用域,局部作用域(不要把执行环境和作用域弄混淆了);

什么是作用域链?

  顾名思义,作用域链是一个像铁链似的链条;

  有链头和链尾(或者说链条的前面和后面);

  链头是全局对象window(通常把window认为是全局执行环境)所处的位置;

  算了算了,来张图吧:

  无论何时何地,你都要记住这三点:

    1.函数的作用域在你调用之前,是不存在的,所以,函数内的变量/方法都是无法访问的,因为不存在函数的执行环境,也就没有作用域,没有作用域,当然就无法访问;

    2.函数调用时,函数的执行环境才会出现,这个时候,才会有局部作用域;

    3.调用结束,函数的执行环境消失了,执行环境都没有了,那环境变量也肯定就没有了,所以作用域也是不存在的;

什么是延长作用域链?

  就是当解释器解释JS代码的时候,执行到例如with、try-catch、if、swich等语句的时候,作用域链会得到加长;

  啥意思呢?

  例如:

var num = 10; if(teru){ var str = '哈哈哈';
}   假如你的JS代码只有这些,当JS解释器解释执行到var num = 10;这里时,作用域链上只有一个变量对象,而当执行了if语句之后,在作用域链上增加了一个变量对象,这样,作用域链就得到了加长;

  而如果作用域链得到了加长,这个变量str就变成了全局变量,成为了这个全局执行环境的一部分,

  如果再函数内,就是整个函数体都可以访问,前提是这个变量所处的位置不在函数体中其他的方法内;它因该处在局部执行环境的最外层;

什么是块级作用域?

  在ES5中只有全局作用域和局部作用域(函数作用域);

  直接看代码把:

复制代码 //全局作用域 var num = 101;//这个num在整个JS脚本中都可以访问或者修改 //局部作用域 function foo(){ var str = 'asd';//这个变量只能在这个函数内才能使用 } //块级作用域 { var name = '小明';//块级作用域中的name变量,只能在这个花括号中访问到,出了花括号是访问不到的,可是JS中并没有块级作用域 } 复制代码   除了在函数中定义的变量,函数之外定义的都是全局变量;

复制代码 var str = 'asd';//全局的 function add(){ var age = 10; } if(true){ var name = '小明';//全局 } for(var i = 0;i<5;i++){ console.log(i); } //for循环中定义的循环变量i也是全局的,如果for循环还有上面的if语句等是在函数内部,那么就是局部的; 复制代码   你声明的变量是怎样一种机制被添加到当前执行环境中的呢?

    当你用var 声明了一个变量,这个时候,变量会自动的找到距离它自己最近的一个执行环境,然后添加上去;

    这样你当前声明变量的环境下面就有了一个当前执行环境的环境变量;

作用域的坑:

  任何时候,任何地方,你使用一个变量都要用关键字去声明,除非你知道在当前或上层作用域链中有这个变量,你就是要用着变量;

  如果你不声明变量就直接赋值使用,那么这个变量不管是在哪儿生命的,他都是一个全局的变量;

  过程是这样的:一个标识符没有声明就直接赋值了,那么就会沿着作用域链开始查找,第一个查找的是当前执行环境下的环境变量,有没有这个标识符,如果有,改变其原值,如果没有,继续向下一级查找,最终找到全局执行环境还是没有的话,就会在window上添加一个全局变量;

作用域链的查找是怎样的?

  你使用的一个变量,不是声明变量,就是在当前环境中读写一个标识符(变量名),先在当前环境下查找这个变量,如果没找到,就向上一级查找,沿着作用域链去查找,找到就拿来用,没找到,就抛出异常,说这个变量未定义:

  看一张图:

你的日积月累,总有一天会成为别人的望尘莫及!