函数作用域
-
函数作用域可以将内部的变量和函数定义隐藏起来
function foo(/*参数*/){ //... } foo(/*参数*/);
但是foo会污染所在作用域,解决这个问题可以通过IIFE(立即执行函数)来解决:
(function foo(/*参数*/){ //... })(/*参数*/); //或者 (function foo(/*参数*/){ //... }(/*参数*/));
这样外部无法访问foo这个函数名。当然你可以直接不写函数名,如下面这样:
(function(/*参数*/){ //... })(/*参数*/);
即匿名函数,但是匿名函数有几个缺点:
- 匿名函数在栈追踪里不会显示出有意义的函数名,调试困难。
- 匿名函数在引用自身时只能使用已过期的
arguments.callee
引用,例如在递归中。
萨达 - 可读性变差。
综上还是建议使用具名函数。
块作用域
JavaScript没有其他编程语言(如java)中的块级作用域(在ES6之前),只有两个with
和try-catch
中的catch
语句块,也可以用上面说的IIFE来模仿块级作用域,ES6中新增了let和const两个关键字,使得JavaScript有了块级作用域。
-
let
let关键字可以将变量绑定到所在的任意作用域中(通常是{...}
内部),换句话说,let为其声明的变量隐式地劫持了所在的块级作用域。let a=2; console.log(a);//可以正常访问
{ let a=2; } console.log(a);//Reference Error
利用上面这一点,显示地声明快作用域是很有用的一个做法,比如可以在涉及闭包时提醒引擎收集不必要的垃圾。
用let声明的变量不会进行变量声明提升。
-
const
用const声明的变量同样是块作用域变量,但const声明的变量是固定的常量,之后任何试图修改值的操作都会引起TypeError错误。用const声明的变量不会进行变量声明提升。
网友评论