在ES5中,只有全局作用域和局部作用域。ES6因为let,const的引入而有了块作用域。
函数作用域
属于这个函数的全部变量都可以在整个函数的范围内使用及复用(在嵌套的作用域中也可以使用)
隐藏内部实现
可以把变量和函数包裹在一个函数的作用域中,然后用这个作用域来“隐藏”它们
为什么"隐藏"变量和函数是一个有用的技术?
有很多原因促成了这种基于作用域的隐藏方法。他们大都是从最小特权原则(最小暴露原则)中引申出来的。
最小特权原则:在软件设计中,应该最小限度的暴露必要内容,而将其他内容都“隐藏”起来。
规避冲突
“隐藏“作用域中的变量和函数所带来的另一个好处,是可以避免同名标识符之间的冲突(命名冲突)
函数声明和函数表达式
在任意代码片段外部添加包装函数,可以将内部的变量和函数定义”隐藏“起来,外部作用域无法访问包装函数内部的任何内容。
但是它会导致额外的问题,首先必须声明一个具名函数foo(),意味着foo这个名称本身”污染“了所在作用域。其次,必须显式的通过函数名调用这个函数才能运行其中代码。
如果函数不需要函数名,并且能够自动运行,这会更加理想。
下面写法可以解决这一问题:
(function foo(){
})()
包装函数的声明以(function...而不是以function...开始,函数会被当作函数表达式而不是一个标准的函数声明来处理。
函数声明和函数表达式之间最重要的区别是它们的名称标识符将会绑定在何处。
function foo(){
}
foo被绑定在所在作用域中,可以直接通过foo来调用它
(function foo(){
})fun
foo被帮顶在函数表达式自身的函数中而不是所在的作用域中
匿名函数表达式
setTimeout (function (){
},100);
这叫做匿名函数表达式,因为没有名称标识符
函数表达式可以是匿名的,而函数声明则不可以省略函数名
立即执行函数表达式
(function foo(){ ..})() 第一个()将函数变成表达式,第二个()执行了这个函数
块作用域
尽管函数作用域是最常见的作用域单元,但其他类型的作用域单元也是存在的
用处:变量的声明应该距离使用的地方越近越好,并最大限度地本地化
块作用域是一个用来对之前的最小暴露原则进行扩展的工具,将代码从在函数中隐藏信息扩展为在块中隐藏信息。
变量声明方式:let
let关键字可以将变量绑定到任意作用域中。
提升是指声明会被视为存在于其所出现的作用域的整个范围内
使用var有变量提升
但是使用let进行声明不会在块作用域中进行提升。声明的代码被运行之前,声明并不存在
声明方式:const
用来创建块作用域变量,但其值是固定的(常量)
const声明的变量虽然不能被重新赋值,但并不意味着他的值不能被改变。例如当const声明的变量是引用类型的时候。