立即执行函数

3.6 立即执行函数

Immediately-Invoked Function Expression (IIFE)

参考自此篇文章

现在我们定义了一个函数function foo(){}或者var foo = function(){}函数名后加上一对小括号即可完成对该函数的调用,比如下面的代码:

var foo = function() {
  /* code */
}
foo()

接着我们来看下面的代码:

function(){ /* code */ }(); // SyntaxError: Unexpected token (
  • 报错了,这是为何?
    这是因为在 javascript 代码解释时,当遇到function关键字时,会默认把它当做是一个函数声明,而不是函数表达式,如果没有把它显视地表达成函数表达式,就报错了,因为函数声明需要一个函数名,而上面的代码中函数没有函数名。以上代码在执行到第一个左括号时报错,理论上是应该有个函数名的。

有意思的是,如果我们给它函数名,然后加上()立即调用,同样也会报错,而这次报错原因却不相同:

function foo(){ /* code */ }(); // SyntaxError: Unexpected token )
  • 为什么会这样?
    在一个表达式后面加上括号,表示该表达式立即执行
    而如果是在一个语句后面加上括号,该括号完全和之前的语句不相关,而只是一个分组操作符,用来控制运算中的优先级(小括号里的先运算)。所以以上代码等价于:
function foo(){ /* code */ }
(); // SyntaxError: Unexpected token )

相当于先声明了一个叫 foo 的函数,之后进行()内的表达式运算,但是()(分组操作符)内的表达式不能为空,所以报错。(以上代码,也就是执行到右括号时,发现表达式为空,所以报错)。

  • 如何解决?
    其实很简单,只需要用括号全部括起来即可,比如下面这样:
(function() {
  /* code */
})()
  • 为什么这样就能立即执行并且不报错呢?
    因为在 javascript 里,括号内部不能包含语句,当解析器对代码进行解释的时候,先碰到了(),然后碰到function关键字就会自动将()里面的代码识别为函数表达式而不是函数声明。

而立即执行函数并非只有上面的一种写法,写法真是五花八门:

// 最常用的两种写法

(function() {
  /* code */
})() // 老道推荐写法
(function() {
  /* code */
})() // 当然这种也可以

// 括号和JS的一些操作符(如 = && || ,等)可以在函数表达式和函数声明上消除歧义
// 如下代码中,解析器已经知道一个是表达式了,于是也会把另一个默认为表达式
// 但是两者交换则会报错
var i = (function() {
  return 10
})()
true &&
  (function() {
    /* code */
  })()
0,
  (function() {
    /* code */
  })()

// 如果你不怕代码晦涩难读,也可以选择一元运算符
!(function() {
  /* code */
})()
~(function() {
  /* code */
})()
-(function() {
  /* code */
})()
+(function() {
  /* code */
})()

// 你也可以这样
new function() {
  /* code */
}()
new function() {
  /* code */
}() // 带参数

3.6.1 为什么要使用 IIFE

  • 不必为函数命名,避免了污染全局变量;

  • IIFE内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值