04. 函数高级-作用域与作用域链
01. 作用域
官方解释是:“一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。”
1. 理解
作用域是指程序源代码中定义变量的区域。
作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。
JavaScript 采用词法作用域,也就是静态作用域。
因为Javascript采用的是词法作用域,所以它的函数的作用域在函数定义的时候就决定了。
而与词法作用域相对的是动态作用域,它的函数的作用域是在函数调用的时候才决定的。
2. 分类
* 全局作用域
* 函数作用域
* 没有块作用域(ES6有了)
3. 作用
* 隔离变量,不同作用域下同名变量不会有冲突
var a = 10, b = 20 function fn(x) { var a = 100, c = 300; console.log('fn()', a, b, c, x) function bar(x) { var a = 1000, d = 400 console.log('bar()', a, b, c, d, x) } bar(100) bar(200) } fn(10) // fn() , 100, 20,300,10 // bar(),1000,20,300,400,100 // bar(),1000,20,300,400,200
02. 作用域与执行上下文
1. 区别1
* 全局作用域之外,每个函数都会创建自己的作用域,作用域在函数定义时就已经确定了。而不是在函数调用时
* 全局执行上下文环境是在全局作用域确定之后, js代码马上执行之前创建
* 函数执行上下文环境是在调用函数时, 函数体代码执行之前创建
2. 区别2
* 作用域是静态的, 只要函数定义好了就一直存在, 且不会再变化
* 上下文环境是动态的, 调用函数时创建, 函数调用结束时上下文环境就会被释放
3. 联系
* 上下文环境(对象)是从属于所在的作用域
* 全局上下文环境==>全局作用域
* 函数上下文环境==>对应的函数使用域
var a = 10,b = 20; function fn(x) { var a = 100,c = 300; console.log('fn()', a, b, c, x) function bar(x) { var a = 1000, d = 400; console.log('bar()', a, b, c, d, x) } bar(100) bar(200) } fn(10) // 'fn()',100,20,300,10 // 'bar()',1000,20,300,400,100 // 'bar()',1000,20,300,400,200
03. 作用域链
1. 理解
* 多个上下级关系的作用域形成的链, 它的方向是从下向上的(从内到外)
* 查找变量时就是沿着作用域链来查找的
2. 查找一个变量的查找规则
* 在当前作用域下的执行上下文中查找对应的属性, 如果有直接返回, 否则进入2
* 在上一级作用域的执行上下文中查找对应的属性, 如果有直接返回, 否则进入3
* 再次执行2的相同操作, 直到全局作用域, 如果还找不到就抛出找不到的异常.
var a = 2; function fn1() { var b = 3; function fn2() { var c = 4; console.log(c); console.log(b); console.log(a); console.log(d); } fn2(); } fn1();
04. 作用域_面试题
// 问题: 结果输出多少? var x = 10; function fn() { console.log(x); } function show1() { var x = 20; function fn2() { console.log(x); } fn2() } function show2(f) { var x = 20; f(); } fn(); // 10 show1(); // 20 show2(fn); // 10