深入理解javascript之IIFE
2015-10-28 20:54
525 查看
IIFE的全称是Immediately-invoked Function Expression,立即执行函数表达式。
在讲IIEF之前,我们首先需要区分函数表达式和函数声明。
这个叫做函数表达式。
这个叫做函数声明。
函数表达式中的函数可以为匿名函数,也可以有函数名,但是该函数实际上不能直接使用,只能通过表达式左边的变量test来调用。
如果我们要调用函数表达式,通过以下方式即可:
如果我们直接使用匿名函数:
就会报错,这是因为浏览器引擎在解释javascript时,遇到function关键字时,会默认把它当做一个函数声明,而不是函数表达式。而函数声明如我们上面所说,需要一个函数名,所以浏览器会认为上面的代码为匿名函数声明,所以报错。
但是,这里需要注意,即使我们给它一个函数名,它依然会报错:
为什么会这样呢?在一个函数表达式后面加上括号,表示该表达式立即执行。但是如果是在一条语句后面加上括号,那么该括号只是用来控制优先级的。所以上面的代码相当于声明了一个函数,然后执行()语句,但是()中内容为空,所以报错。
所以最后的解决办法就是写成如下形式:
这样就不会报错了,因为当解释器遇到(后,会认为其中的function不是函数声明而是函数表达式,所以就成功啦。
IIFE可以带来块状作用域效果:
当然,还有其他多种方法立即执行匿名函数:
在Bootstrap源码中就使用了大量的IIFE:
最后,注意一下函数表达式和函数声明的使用。请看代码:
输出结果为1,这个很好理解,那么我们调整一下执行foo的位置呢:
这里就是未定义。这是由于变量提升。javascript解释器在解释代码时会将变量声明先提升到块级作用域最前端,也就是这个样子:
那么我们看看使用函数声明时的结果:
咦,这里怎么又输出2了呢?原来函数声明和变量一样,都有一个提升的过程,而和函数表达式只会提升声明不一样,函数声明即会提升声明,也会提升定义,所以第二个foo的定义把第一个foo给替换掉了。
这里需要格外注意。
在讲IIEF之前,我们首先需要区分函数表达式和函数声明。
var test = function(){};
这个叫做函数表达式。
function test(){};
这个叫做函数声明。
函数表达式中的函数可以为匿名函数,也可以有函数名,但是该函数实际上不能直接使用,只能通过表达式左边的变量test来调用。
如果我们要调用函数表达式,通过以下方式即可:
var test = function(){}; test();
如果我们直接使用匿名函数:
function(){}()//SyntaxError:Unexpected token(
就会报错,这是因为浏览器引擎在解释javascript时,遇到function关键字时,会默认把它当做一个函数声明,而不是函数表达式。而函数声明如我们上面所说,需要一个函数名,所以浏览器会认为上面的代码为匿名函数声明,所以报错。
但是,这里需要注意,即使我们给它一个函数名,它依然会报错:
function test(){}();//SyntaxError:Unexpected token )
为什么会这样呢?在一个函数表达式后面加上括号,表示该表达式立即执行。但是如果是在一条语句后面加上括号,那么该括号只是用来控制优先级的。所以上面的代码相当于声明了一个函数,然后执行()语句,但是()中内容为空,所以报错。
所以最后的解决办法就是写成如下形式:
(function (){}());
这样就不会报错了,因为当解释器遇到(后,会认为其中的function不是函数声明而是函数表达式,所以就成功啦。
IIFE可以带来块状作用域效果:
var a = 2; (function IIFE(){ var a = 3; console.log( a ); // 3 })(); console.log( a ); // 2
当然,还有其他多种方法立即执行匿名函数:
(function(){})(); void function(){}(); //使用void !function(){}();//使用一元运算符 ~function(){}(); -function(){}(); +function(){}();
在Bootstrap源码中就使用了大量的IIFE:
+function ($) { }(window.jQuery);
最后,注意一下函数表达式和函数声明的使用。请看代码:
if (true) { var foo = function(){ document.write( "1" ); } } else { var foo = function(){ document.write( "2" ); } } foo();//1
输出结果为1,这个很好理解,那么我们调整一下执行foo的位置呢:
foo();//undefined if (true) { var foo = function(){ document.write( "1" ); } } else { var foo = function(){ document.write( "2" ); } }
这里就是未定义。这是由于变量提升。javascript解释器在解释代码时会将变量声明先提升到块级作用域最前端,也就是这个样子:
var foo; foo();//undefined if (true) { foo = function(){ document.write( "1" ); } } else { foo = function(){ document.write( "2" ); } }
那么我们看看使用函数声明时的结果:
if (true) { function foo() { document.write( "1" ); } } else { function foo() { document.write( "2" ); } } foo(); // 2
咦,这里怎么又输出2了呢?原来函数声明和变量一样,都有一个提升的过程,而和函数表达式只会提升声明不一样,函数声明即会提升声明,也会提升定义,所以第二个foo的定义把第一个foo给替换掉了。
这里需要格外注意。
相关文章推荐
- JS完美运动框架
- 京东首页很炫的js效果、图片自动滑动,悬停效果,鼠标离开效果
- javascript基础之confirm
- 天气API整理,返回的数据格式为json对象
- JS中通过建立类来防止方法重载
- javascript入门
- JS对象在用于搜索和分析数据上表现出十分便捷的作用,它们甚至连排列数字也不费吹灰之力
- javascript入门
- 【JSP】让HTML和JSP页面不缓存从Web服务器上重新获取页面
- JS下对象的复习要点
- JS下的每个字符串都是个对象
- JS中的字符串是对象,包含许多与字符串数据交互的方法(lengh,charAt(),toUpperCase(),toLowerCase())
- JS会自动调用toString()方法来显示日期(即“Date对象的内容”)
- JS中的自带对象Date
- JS中的如何构造自定义对象
- extjs panel layoutconfig属性
- javascript客户端检测技术
- javascript 继承 学习总结
- javascript: with 表单验证
- 10个可创建交互式地图的免费JavaScript工具