作用域与作用域链
作用域
-
理解
- 即一块”地盘“,一个代码段所在的区域
- 它时静态的(相对于上下文对象),在编写代码时确定
-
分类
-
全局作用域
-
函数作用域(局部作用域)
-
没有块作用域(ES6)
if(true){ var c = 1 } console.log(c)// 1 大括号并不影响c,在外部能看见变量
-
-
作用
- 隔离变量,不同作用域下同名变量不会冲突
-
总结
- n+1原则,n为定义函数个数,1为全局作用域,得出总作用域个数
作用域与执行上下文
- 区别1
- 全局作用域之外,每个函数都会创建自己的作用域(n+1),作用域在函数定义时就已经确定了。而不是在函数调用时
- 全局执行上下文环境是在全局作用域确定之后,JS代码马上执行之前创建
- 函数执行上下文是在调用函数时,函数代码准备执行之前创建
- 区别2
- 作用域是静态的,只要函数定义好了就一直存在,且不再变化
- 执行上下文环境是动态的,调用函数时创建,函数调用结束时执行上下文环境会被自动释放
- 联系
- 执行上下文环境(对象)是从属于所在的作用域
- 全局执行上下文环境==>全局作用域
- 函数执行上下文环境==>对应的函数使用域
作用域链
类似于原型链,嵌套作用域,由内向外逐层查询变量,直到全局作用域,若还是未找到则报错 ,即外部不能看到内部,但内部可以往外部找
【注】a.b,先在作用域链上找a,找不到报错,.b在原型链上查找,找不到返回undefined。window.a,找不到a返undefined,而单独a找不到报错!
面试题
var x = 10
function fn() {
console.log(x)
}
function show(f) {
var x = 20
f()
}
show(fn) //10 函数作用域在定义时就确定了,跟调用没有关系,不会改变
var fn = function () {
console.log(fn)
}
fn()//输出这个函数
var obj = {
fn2:function () {
console.log(fn2) //这里的fn2是个变量,只是和obj的属性fn2一样具有迷惑性但并不是同一个
//console.log(this.fn2) 就能输出函数
}
}
obj.fn2()//报错fn2未找到 现在函数作用域找fn2未找到,再到全局找也没找到