函数作用域和块作用域

# 函数作用域和块作用域

函数作用域和块作用域 是在写代码时定义的。

# 函数中的作用域

JavaScript 具有基于函数的作用域

函数作用域的含义是指,属于这个函数的全部变量都可以在整个函数的范围内使用及复 用

# 隐藏内部实现

可以把变量和函数包裹在一个函数的作用域中,然后用这个作用域 来“隐藏”它们

最小授权或最小暴露原则

变量或函数本应该是私有的,正确 的代码应该是可以阻止对这些变量或函数进行访问的。

规避冲突

    1. 全局命名空间
    1. 模块管理

# 函数作用域

区分函数声明和表达式最简单的方法是看 function 关键字出现在声明中的位 置(不仅仅是一行代码,而是整个声明中的位置)。如果 function 是声明中 的第一个词,那么就是一个函数声明,否则就是一个函数表达式。

函数声明和函数表达式之间最重要的区别是它们的名称标识符将会绑定在何处。

匿名和具名

匿名函数表达式,因为 function().. 没有名称标识符。

函数表达式可以是匿名的, 而函数声明则不可以省略函数名——在 JavaScript 的语法中这是非法的。

匿名函数表达式

  1. 匿名函数在栈追踪中不会显示出有意义的函数名,使得调试很困难。
  2. 如果没有函数名,当函数需要引用自身时只能使用已经过期的 arguments.callee 引用, 比如在递归中。另一个函数需要引用自身的例子,是在事件触发后事件监听器需要解绑 自身。
  3. 匿名函数省略了对于代码可读性 / 可理解性很重要的函数名。一个描述性的名称可以让 代码不言自明。

立即执行函数表达式

由于函数被包含在一对 ( ) 括号内部,因此成为了一个表达式,通过在末尾加上另外一个 ( ) 可以立即执行这个函数,比如 (function foo(){ .. })()。第一个 ( ) 将函数变成表 达式,第二个 ( ) 执行了这个函数。

给它规定了一个术语:IIFE 代表立即执行函数表达式 (Immediately Invoked Function Expression)

函数名对 IIFE 当然不是必须的,IIFE 最常见的用法是使用一个匿名函数表达式。虽然使 用具名函数的 IIFE 并不常见,但它具有上述匿名函数表达式的所有优势

改进的形式:(function(){ .. }())

第一种形式中函数表达式被包含在 ( ) 中,然后在后面用另一个 () 括 号来调用。第二种形式中用来调用的 () 括号被移进了用来包装的 ( ) 括号中。

进阶用法是把它们当作函数调用并传递参数进去。

我们将 window 对象的引用传递进去,但将参数命名为 global,因此在代码风格上对全局 对象的引用变得比引用一个没有“全局”字样的变量更加清晰。当然可以从外部作用域传 递任何你需要的东西,并将变量命名为任何你觉得合适的名字。这对于改进代码风格是非 常有帮助的。

IIFE 还有一种变化的用途是倒置代码的运行顺序,将需要运行的函数放在第二位,在 IIFE 执行之后当作参数传递进去。这种模式在 UMD(Universal Module Definition)项目中被广 泛使用。尽管这种模式略显冗长,但有些人认为它更易理解。

# 块作用域

with

用 with 从对象中创建出的作用域仅在 with 声明中而非外 部作用域中有效。

try/catch

JavaScript 的 ES3 规范中规定 try/catch 的 catch 分句会创建一个块作 用域,其中声明的变量仅在 catch 内部有效。

let

let 关键字可以将变量绑定到所在的任意作用域中(通常是 { .. } 内部)。

提升是指声明会被视为存在于其所出现的作用域的整个范围内

但是使用 let 进行的声明不会在块作用域中进行提升。

  1. 垃圾收集

块作用域非常有用的原因和闭包及回收内存垃圾的回收机制相关。

  1. let循环

for 循环头部的 let 不仅将 i 绑定到了 for 循环的块中,事实上它将其重新绑定到了循环 的每一个迭代中,确保使用上一个循环迭代结束时的值重新进行赋值。

const

const,同样可以用来创建块作用域变量,但其值是固定的 (常量)。之后任何试图修改值的操作都会引起错误。

# 小结

  • 函数是 JavaScript 中最常见的作用域单元。本质上,声明在一个函数内部的变量或函数会 在所处的作用域中“隐藏”起来,这是有意为之的良好软件的设计原则
  • 块作用域指的是变量和函数不仅可以属于所处的作用域, 也可以属于某个代码块(通常指 { .. } 内部)
  • 从 ES3 开始,try/catch 结构在 catch 分句中具有块作用域。
上次更新: 2022/7/21 上午10:29:33