立即执行函数
立即执行函数:函数在定义后立即被执行,有特定的书写模式。例如:
(function () { alert('watch out!'); }());
或:
(function () { alert('watch out!'); })();
这种模式本质上就是函数表达式(命名的或者匿名的),在创建后立即执行;立即执行函数并不是标准的叫法,是自我理解的叫法。
下面这种写法是错误的:(即将最外层的左右原括号去掉。)
function () { alert('watch out!'); }();
//函数声明形式,是一个语句。 //报错:Uncaught SyntaxError: Unexpected token (
var result = function(){
alert('watch out!');
}();
//函数表达式形式,是一个表达式
//不报错
原因:在一个表达式后面加上括号(),该表达式会立即执行,但是在一个语句后面加上括号(),是完全不一样的意思,他的只是分组操作符。
要解决上述问题,非常简单,我们只需要用大括弧将代码的代码全部括住就行了,因为JavaScript里括弧()里面不能包含语句,所以在这一点上,解析器在解析function关键字的时候,会将相应的代码解析成function表达式,而不是function声明。
所以立即执行函数需要有一个()!!!!
考虑一下下面这种常见的场景:
1、你的代码在页面代码加载完成之后,不得不执行一些设置工作,比如附加时间处理器,创建对象等等,
2、所有的这些工作只需要执行一次,所以没有理由创建一个可复用的命名的函数,
3、但这些代码也需要一些临时的变量,但初始化过程结束后,就再也不会被用到了,所以将这些变量作为全局变量不是个好主意,所以我们需要立即执行函数——去将我们所有的代码包裹在它的局部作用域中,不会让任何变量泄露成全局变量;
(function() { var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], today = new Date(), msg = 'Today is ' + days[today.getDay()] + ', ' + today.getDate(); alert(msg); } ()); // "Today is Fri, 13"
如果代码没有被包裹在立即执行函数中,那么局部变量days,today和msg都将成为全局变量,初始化代码的遗留产物。
立即执行函数的参数
传递参数方式如下:
(function(who, when) { console.log("I met " + who + " on " + when); } ("Joe Black", new Date()));
通常,全局变量被作为一个参数传递给立即执行参数,这样它在函数内部不使用window也可以被访问到:这种方式可以让代码在环境(除了浏览器)中更加通用:
(function (global) { // access the global object via `global` }(this));
立即执行函数的返回值
就像其它任何函数一样,一个立即执行函数也能返回值并且可以复制给其它变量:
var result = (function () { return 2 + 2; }());
除了基本类型值,立即执行函数也能返回任何类型的值,包括其它的函数;
那么,你可以利用立即执行函数的作用域为返回的内部函数私下里存储一些数据。
在接下来的例子中,立即执行函数的返回值是一个函数——被赋值给了变量getResult,这个函数简单的返回了res的值,这个值事先被计算并被储存在立即执行函数的闭包中:
var getResult = (function() { var res = 2 + 2; return function() { return res; }; } ());
立即执行函数也可以用来定义对象的属性;
假如,你需要定义一个很可能在对象生命周期中都不会改变的属性,但在你定义之前,你需要做一下工作去计算出正确的值;
你可以使用立即执行函数去封装这些工作,并且立即执行函数的返回值将会成为属性的值,下面的代码:
var o = { message: (function() { var who = "me", what = "call"; return what + " " + who; } ()), getMsg: function() { return this.message; } }; // usage o.getMsg(); // "call me" o.message; // "call me"
在这个例子中,o.message是一个字符串类型的属性,不是一个函数,但它需要一个函数在脚本被载入时被执行并帮忙定义属性。
通过这个例子感觉String对象的length属性就是一个立即执行函数算出来的。