作用域是在运行时代码中的某些特定部分中的变量、函数和对象的可访问性。即作用域决定了代码区块中变量和其他资源的可见性。
function change(){
var a = 'ellie'
}
change() //要事先调用一下,不然读不到函数内部(js执行顺序)
console.log(a:', a) //a is not undefined
作用域就是一个独立的地盘,让变量不会外泄、暴露出去。
最大的用处:隔离变量,不同作用域下同名变量不会出现冲突。
ES6之前javascript没有块级作用域,只有全局作用域和函数作用域。ES6新增了块级作用域,可通过let const实现.
全局作用域 和局部作用域
全局作用域
在代码中任何地方都能访问到的对象拥有全局作用域,这几种情况拥有全局作用域
- 最外层函数、最外层函数外面定义的变量,拥有全局作用域
var a = 'ellie' // 最外层变量
fuction change(){ // 最外层函数
var b = 'jerry' // 内层变量
fuction innerChange(){ // 内层函数
console.log('b:', b)
}
}
- 所有未定义直接复制的变量会自动声明,拥有全局作用域
function change(){
a = 'ellie'
var b = 'jerry'
}
change()
console.log(a) //ellie
console.log(b) // b is not undefined
- 所有window对象的属性拥有全局作用域
一般情况下,
window.alert,window.location等 全局作用域的弊端:如果多人协作,并且变量定义都没有用函数包裹,那这些变量都是在全局作用域中,如果两个人命名相同,就会出现命名冲突的问题。
函数作用域
函数作用域是指声明在函数内部的变量。只在固定的代码片段内可访问到
function change(){
var a = 'ellie'
function innerChange(){
console.log('a:', a)
}
}
console.log(a); // a is not undefined 阻塞掉后面掉执行,即使执行,也报错
innerChange()
内层作用域可以访问外层作用域,外层作用域不能调用内部作用域。
另:块语句(即:花括号中间的语句)不会创建一个新的作用域。
if(true){
var a = 'ellie'
}
console.log(a) // ellie
块级作用域
块级作用域可通过let const 声明,所声明的变量在指定的块的作用域外无法被访问,创建条件:
- 一个函数内部
- 一个代码块内部(花括号包裹内) 块级作用域的特点:
- 声明不会被提升到当前代码块的顶部
- 禁止重复声明
- 循环中绑定块级作用域的妙用(for循环中)
作用域链
自由变量
自由变量:当前的作用域中没有定义的变量。
var a = 'ellie'
function change(){
var b = 'jerry'
console.log(a) //这里a就是一个自由变量
console.log(b)
}
自由变量如何得到值:要到创建函数的那个作用域中取,无论函数在哪里调用
var a = 'ellie'
function change(){
console.log(a)
}
change() // ellie
function show(){
var a = 'jerry'
change() // 全局作用域下创建的,所以打印的a还是全局下的a。跟在哪里调用的无关
}
show() // ellie