这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战
前言
在上一篇文章中,我们刚好讲了const和let命令,里面简单说了点作用域的内容。那么就书接上回,再来讲讲js的作用域。
在es6之前,js的作用域是只有全局作用域和函数作用域的。 es6新增了块级作用域。下面来展开说说js的作用域。
全局作用域
全局作用域,顾名思义,就是存在最顶端的作用域,全局都能访问。
var name = '答案cp3'
function getName () {
console.log(name) // 答案cp3
}
getName()
if(true) {
console.log(name) // 答案cp3
}
可以看到,在全局作用域声明的变量,不管在哪都能访问的到。
函数作用域
函数作用域,就是存在函数内部的作用域,仅在函数内部能访问。
function getName () {
var name = '答案cp3'
return name
}
getName() // 答案cp3
console.log(name) // ''
可以看到,在getName内部声明的变量,无法在外部的作用域访问到。
块级作用域
之所以es6要引入块级作用域,是因为之前的作用域可能会存在以下问题:
-
变量提升导致变量被覆盖
var name = '答案cp3' function getName () { console.log(name) var name = 'cp3' } getName() // undefinedvar声明导致变量提升,导致打印出的
name是undefined。 -
在for循环中,var声明的变量,在for循环结束后还能继续访问
for(var i = 0; i < 5; i++) { console.log(i) // 0 1 2 3 4 5 } console.log(i) // 5
块级作用域,就是限制变量的声明只在这块区域可以访问到。一般是由{}包裹的里面代码块形成块级作用域,比如if语句,while语句,for循环语句, try-catch语句等
另外,块级作用域一般是要配合let, const一起使用。
改写上面的例子:
for(let i = 0; i < 5; i++) {
console.log(i) // 0 1 2 3 4 5
}
console.log(i) // i is not defined
let声明的 i,只在for循环里面可以访问,for循环结束后无法再访问。
块级作用域之间的变量声明互不影响,内层的声明可以覆盖外层的同名变量。
如代码所示:
if(true) {
let name = '答案'
console.log(name) // 答案
}
if(true) {
let name = 'cp3'
console.log(name) // cp3
}
if(true) {
let name = '答案'
if(true) {
let name = 'cp3'
if(true) {
let name = '答案cp3'
console.log(name) // 答案cp3
}
}
}
补充一点(参考来自阮一峰的块级作用域):
在块级作用域中函数声明(不建议这样写),如果你是在es6的浏览器中运行代码,则函数声明会变量提升,如果是在其它环境运行,则不会变量提升。
// 不建议, 函数声明尽量在全局作用域中声明或者在函数作用域声明
if(true) {
console.log(fn) // 在es6的浏览器中fn会提升
function fn() {}
}
块级作用域必须要有
{}包裹
总结
以上就是我总结的js的作用域:
- 全局作用域,全局都能访问的作用域
- 函数作用域,只存在函数内部的作用域
- 块级作用域, 只在
{}内的代码块访问到的作用域,配合let/const使用,可以避免变量提升和变量污染等问题
感谢你们的阅读。