IIFE-立即执行函数表达式
IIFE,全拼是 Immediately-Invoked Function Expression 。
函数声明与函数表达式
函数声明
function foo () { console.log('Hi foo') }
函数表达式
var fuu = function () { console.log('Hi fuu') }
区别
函数声明与变量声明一样,会在代码本身被执行前(编译阶段)先提升到各自作用域的顶端。(注意:函数声明提升优先于变量声明的提升)
foo() // Hi foo fuu() // Uncaught TypeError: fuu is not a function // 函数声明会提升 function foo () { console.log('Hi foo') } // 函数表达式不会提升 var fuu = function () { console.log('Hi fuu') }
IIFE知识点
// 报错原因:函数声明关键字function后未提供函数名 function(){ /* code */}() // Uncaught SyntaxError: Function statements require a function name // 报错原因:第二个圆括号被认为是运算符,需要包裹表达式 function foo(){ /* code */ }() // Uncaught SyntaxError: Unexpected token ) // 正确执行,输出1 function foo(){/* code */}(1) // 上面的代码等同于如下,一个函数声明跟着一个完全没有关系的表达式 function foo(){/* code */} (1) // 在函数表达式中允许匿名函数,这比较符合认知 var foo = function(){console.log('Yes')}() // 输出Yes。但foo是undefined,因为并没有值可赋给它。 // 当圆括号包裹函数时,它会默认将函数作为表达式去解析,而不是函数声明 ( function(){console.log('Yes')} )() ( function foo(){ console.log('Yes')} )() // 外层括号内的表达式是立即执行函数表达式^_^ ( function(){console.log('Yes')} () ) ( function foo(){console.log('Yes')} () ) // 以上立即执行函数表达式都可以将return值赋值给一个变量 var res = ( function foo(){return 'Yes'} () )
关于圆括号 ( )
运算符,《JavaScript高级程序设计》一书中没有介绍,MDN上介绍为:圆括号运算符 ( )
用于控制表达式中的运算优先级,比如 (1 + 2) * 3 。哦,恍然大悟。 所以 ( )
运算符中必须要有表达式,否则报语法错误。
问题代码解析
console.log(1, typeof g) var f=function(){return true}; console.log(2, typeof g) var g=function(){return false}; console.log(3, typeof g); ;(function(){ console.log(4, typeof g) if ((g() && []) == ![]) { console.log(5, typeof g) f = function(){return false}; console.log(6, typeof g) function g() {return true}; console.log(7, typeof g) } console.log(8, typeof g) } )(); console.log(9, typeof g) var c = f(); console.log(10, typeof g) var b = g(); console.log(11, typeof g)
执行以上代码会报 g is not a function,原因是在第4个console后面执行g()的时候,因为下面的函数声明function g(),此时有g变量,但是值为undefined,所以报错