说作用域和作用域链之前需要明白几个概念:执行环境、变量对象、作用域、作用域链
执行环境是JavaScript中重要的概念,其中定义了变量或函数有权访问的其他数据,决定他们各自的行为。在每个执行环境中都有与之关联的变量对象 ,执行环境中定义的所有变量和函数都保存在这个对象中。
代码在执行环境中执行时,会创建变量对象的作用域链(作用域链可以保证对执行环境有权访问的所有变量和函数的有序访问);
执行环境分为:全局执行环境(最外围的执行环境)、函数执行环境
全局执行环境:在Web浏览器中,全局执行环境被认为是window对象(所有全局变量和函数都是作为window对象的属性和方法创建的),全局执行环境一般是应用退出(关闭网页或浏览器的时候)才会被销毁。
函数执行环境:代码执行进入函数中时,函数的执行环境就会被推入一个环境栈中,函数执行完以后,栈将其环境弹出,把控制权返回给之前的执行环境,函数执行完函数的环境就被销毁了。
全局:一般指window对象所在的作用域;
局部作用域:一般指函数内部(函数的{}内部),ES6中引入块级作用域的概念注意区分。
作用域链中,①最开始是当前执行代码所在的执行环境的变量对象,(如果执行环境是函数,就把他的活动对象(函数最开始时的活动对象只包含arguments对象)作为变量对象),②作用域链中的下一个变量对象来自外部环境(又叫包含环境),③再下一个变量对象来自来自下一个外部环境…④就这样一直延续到全局执行环境中(全局执行环境中的变量对象始终是作用域链中最后一个对象)
注意注意:标识符解析的时候是按照作用域链一级一级的搜索标识符。搜索过程始终是从作用域链的前端开始,逐级向后回溯,直到找到标识符为止(找不到的话就会报错了)
代码解析作用域链(结合代码和图片来看)
var whoPeople = "da"; function lovedan (){ var love = "dan"; function howtime (){ var howLong = "forever" // console.log(whoPeople,love,howLong) da dan forever } //console.log(whoPeople,love) da dan 不可以输出howLong } // console.log(whoPeople) da 不可以输出love 和 howLong // 可以看出,作用域链是向上访问的,不可以向下访问
以上代码中有,3个执行环境,分别是:全局执行环境、函数lovedan()执行环境、howtime()执行环境,图片中三个矩形分别表示这三个执行环境。
根据代码输出可得出,内部执行环境可以通过作用域链访问所有的外部执行环境,而外部执行环境不能访问内部执行环境中的任何变量和函数,这些环境之间的联系是线性的、有次序的。任何环境都可以向上搜索作用域链,来查询变量和函数名,但是任何执行环境都不能通过向下搜索作用域链,而进入另一个执行环境。
这个例子中对于howime()而言,他的作用域链中有三个变量对象:howtime()的变量对象、lovedan()的变量对象和全局变量对象;howtime()中的代码开始执行的时候会先在自己的变量对象中寻找变量和函数名,如果找不到会到上一级作用域链中找(lovedan()中找),如果还找不到就到上一级中继续找(全局执行环境,全局执行环境或全局作用域中找不到的话就会出现错误)。
用一句不太准确的话概括:访问变量时会现在当前作用域寻找,找不到会到上一级作用域找,一直找到全局作用域中,如果全局中找不到就要报错啦。
写完啦,后续有需要更正或者更新的地方会及时更新的!!!
下期预告 原型和原型链