作用域定义
作用域就是一块地盘,一个代码段所在的区域。 它是静态的(相对于执行上下文),在编写代码的时候作用域就确定了。
作用域的分类
- 全局作用域:变量全局可见
- 函数作用域:变量函数内可见
- 没有块作用域:(但是在ES6之后有了)
块作用域即大括号作用域,即在大括号内定义的变量,大括号外不可见,但是JS没有块作用域 eg:
if(true){
var c =3
}
console.log(c)
输出:
3
作用域的个数
如果定义了n个函数,那么作用域的个数就是 n+1 个。
作用域的作用
- 隔离变量,不同作用于下同名变量不会有冲突
- 即局部作用域其实是封闭的
eg:
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)
输出:  作用域图示: 
作用域与执行上下文
区别
产生时机的不同
作用域:
- 全局作用域:在编写代码的时候就已经产生
- 函数作用域:每个函数都会创建自己的作用域,作用域在函数定义时就已经确定了。而不是在函数调用时,也不是在函数预处理时(预处理的时候是执行函数定义)
执行上下文: - 全局执行上下文 :是在全局作用域确定之后,js代码执行之前创建的
- 函数执行上下文 :是在调用函数时,函数体代码执行之前创建
动静态区别
- 作用域是静态的,只要函数定义好了就一直存在,且不会再变化
- 执行上下文是动态的,调用函数时创建,函数调用结束时就会自动释放
(函数的内存也是在函数调用时产生,函数执行完释放——局部变量的临时性)
联系
执行上下文(对象)是从属于所在的作用域的: 全局执行上下文==>全局作用域 函数执行上下文==>对应的函数使用域
eg:  注意作用域中存储变量,但是使用到变量的时候还是从执行上下文中进行查找。 
作用域链
嵌套的作用域产生的有内向外的链。
定义
多个上下级关系的作用域形成的链,它的方向是从下向上的(从内到外) eg: 
变量的查找
查找变量时就是沿着作用域链在执行上下文函数中来查找的 查找一个变量的查找规则:
- 在当前作用域下的执行上下文中查找对应的属性,如果有直接返回
- 否则进入上一级作用域的执行上下文中查找对应的属性,如果有直接返回
- 否则再进入上一级作用域的执行上下文中查找对应的属性,直到全局作用域,如果还找不到就抛出找不到的异常
题目
题1
var x =10
function fn (){
console.log(x)
}
function show (f){
var x =20
f()
}
show(fn)
输出:
10
原因:作用域是在写代码的时候就已经确定好了的,而且执行上下文对应的属性和属性值就是根据作用域确定的 如下:  所以输出10
题2
var fn= function (){
console.log(fn)
}
fn()
var obj ={
fn2:function(){
console.log(fn2)
}
}
obj.fn2()
输出:  原因: 
所以想要输出fn2时应该使用this.fn2 eg :
var obj ={
fn2:function(){
console.log(this.fn2)
}
}
obj.fn2()

|