一、作用域
作用域是指程序源代码中定义变量的区域。
作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。
在 JavaScript 采用词法作用域(lexical scoping),也就是静态作用域。
JavaScript 将作用域分为两种 全局作用域 和 函数作用域。
静态作用域与动态作用域
因为 JavaScript 采用的是词法作用域,函数的作用域在函数定义的时候就决定了。
而与词法作用域相对的是动态作用域,函数的作用域是在函数调用的时候才决定的。
全局作用域
代码在程序的任何地方都能被访问,window 对象的内置属性都拥有全局作用域。
函数作用域
在固定的代码片段才能被访问
// 全局作用域
var a = 10,
b = 20;
function fn() { // fn 作用域
var a = 1000,
b = 2000;
function bar() { // bar 作用域
var a = 1000,
b = 2000;
}
}
作用域有上下级关系,上下级关系的确定就看函数是在哪个作用域下创建的。如上,fn 作用域下创建了 bar 函数,那么“ fn 作用域”就是“ bar 作用域”的上级。
作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。
块级作用域
JavaScript 没有块级作用域,仅有全局作用域和函数作用域两种作用域。
ES6 通过对全局作用域的特殊实现,实现了 js 的块级作用域 let;
let 的生效范围为 { };
const 为定义常量。
注:定义的常量的值存储的内存地址不可变动,值是可变的比如常量中定义的是数组 或者对象时候,可以通过数组或对象方法操作原数据,只要不重新赋值就没问题。
注:es6实现let 块级作用域不是js原生的,底层同样是通过var实现的。如果想了解具体细节,请访问babel官方 对es6中let 进行解析。
二、作用域链
- 自由变量:当前作用域没有定义的变量,但是上层作用域定义了,可以在此层作用域中使用的变量。
- 作用域链:当使用一个变量时候,先在自己的作用域里找,如果没有找到,再到父级作用域找,一直找到全局作用域,如果都没有找到即报错。
由此这样一个查找过程形成的链条就叫做作用域链。