实行环境(也就是常说的上下文)和作用域是js中很基本也很主要的观点, 但在许多时刻,特别是看其他的文档的时刻,却轻易殽杂观点,这篇文章试着梳理下实行环境和作用域的观点。
1、实行环境
实行环境定义了变量或函数有权接见的其他数据,决议了它们各自的行动。每一个实行环境都有一个相关联的变量对象,这个对象内里保留了环境中定义的一切变量和函数。这个变量对象在编写代码是不能接见的(除了最外层的window对象),只要剖析器在背景处置惩罚才运用。
实行环境能够分红两种:全局实行环境和函数实行环境。在实行js代码之前,默许都邑建立一个全局的实行环境,与之关联的是window对象,内里保留了一切全局变量和函数,直到页面封闭时才烧毁。而当实行某个函数时,会建立一个运动对象,并把这个对象作为与该函数的实行环境关联的变量对象,从而建立出函数的实行环境。函数的实行环境在函数实行完以后,就会被烧毁。
别的,须要提一句的是:在运动对象刚被建立时,对象中只要arguments对象一个属性。
2、作用域
相识实行环境,就能够来讲作用域了。
在js中,实行环境是用环境栈来治理的。最底层的是全局实行环境,当实行到一个函数, 函数的实行环境就会被推入到环境栈中。假如在函数中继承实行函数,那末内部函数的实行环境就继承被推入环境栈。比方下面的代码:
var name = 'window';
outer();
function outer(){
var name = 'outer';
inner();
//函数内部的函数
function inner(){
var name = 'inner';
console.log(name);
}
}
对应的环境栈以下:
环境栈中的变量对象,从上到下就构成一条作用域链, 用来保证对实行环境有权接见的一切变量和函数的有序接见。剖析标识符时,就沿着作用域链一级一级地搜刮,也就在环境栈中从上向下一个个对象搜刮,直到找到标识符,就返回,不然就报错。比方,上面的代码,实行后会输出‘inner’,当把inner函数中的定义变量语句解释以后就输出‘outer’。
2、延伸作用域链
在两种情况下,虽然不是在实行函数,但也会在作用域链的前端暂时增添一个变量对象:
try-catch语句的catch块
with 语句
在实行with 语句时,会将指定的对象增加到作用域链中。比方:
function getHost() {
var res = '';
with(location){
res = host;
}
return res;
}
在上面的代码中,实行with语句时,作用域链的最顶端是暂时增加的location对象,因而能够直接接见location对象的host属性获取值。
在实行catch语句时,会建立一个新的变量对象(该对象中包括被抛出的毛病对象),并增加到作用域链的顶端。正因为这个缘由,在js的编程中,假如不是必要的,不发起在代码中运用try-catch语句块。
备注:
在第一个例子中,我们把inner函数定义在outer函数的内部,假如是定义在outer函数外部呢?会不会有什么差别?缘由是什么?
写在末了:
假如以为我写的文章对你有协助,迎接扫码关注我的民众号:海痕笔记
微信号:haihenbiji