你不知道的JS系列 ( 9 ) - 函数表达式

在任意代码片段外部添加包装函数,可以将内部的变量和函数定义“隐藏”起来,外部作用域无法访问包装函数内部的任何内容。

 

var a = 2;
function foo() {
  var a = 3;
  console.log(a); // 3
}
foo();
console.log(a); // 2

 

虽然这种技术可以解决一些问题,但是会导致一些额外的问题。

1、foo 这个名称本身污染了所在作用域(在这个例子中是全局作用域)
2、必须显式地通过函数名调用才能运行

 

为了解决额外的问题,如果函数名不需要(或者至少函数名可以不污染所在作用域),并且能够自动运行,将会更加理想
var a = 2;
(function foo(){
  var a = 3;
  console.log(a);
})()
console.log(a);

比较一下两段代码,第一段 foo 被绑定在全局作用域中,通过 foo 来调用它。第二段 foo 被绑定在函数表达式自身的函数中,而不是所在的作用域。foo 变量名被隐藏在自身中不会污染外部作用域

 

如果 function 是声明中的第一个词,那么就是一个函数声明,否则就是一个函数表达式
 
函数表达式最熟悉的场景可能就是回调参数了,比如

setTimeout(function(){
  console.log('i wait 1 second')
}, 1000)
这叫匿名函数表达式,函数表达式可以是匿名的,而函数声明则不可以省略函数名

很多库和工具也倾向鼓励使用这种风格的代码。但是它有几个缺点
1、匿名函数在栈追踪时不会显示有意义的函数名,使得调试很困难
2、一个函数需要引用自身的例子,在事件触发后事件监听器需要解绑自身,这时候做不了
3、匿名函数省略了代码可读性,一个描述性的名称可以让代码不言自明

行内函数表达式非常强大且有用-匿名和具名之间并不会对这点有任何影响,防止上述缺点,给出一个最佳实践
setTimeout(function timeoutHandler(){
  console.log('i wait 1 second')
}, 1000)

 

posted @ 2020-02-19 09:53  wzndkj  阅读(249)  评论(0编辑  收藏  举报