在JS
中,这两种写法,都是一种立即执行函数
的写法,即IIFE (Immediately Invoked Function Expression)
。这种函数在函数定义的地方就直接执行了。
关于立即执行函数,可参考:
通常函数的声明和函数的调用写法分别如下:
function login() // 这是定义,Declaration;定义只是让解释器知道其存在,但是不会运行。
{
// 获取用户输入的账号和密码
var name = $('#count').val();
var password = $('#password').val();
$.ajax({
url : 'account/login.do',
type : 'post',
// data对象中的属性名要和服务端控制器的参数名一致 login(name, password)
data : {
'name' : name,
'password' : password
},
dataType : 'json',
success : function(result) {
if (result.state == 0) {
// 登录成功,设置cookie并跳转edit.html
addCookie('userId', result.data.id);
addCookie('nick', result.data.nick);
location.href = 'edit.html';
} else {
// 登录失败
var msg = result.message;
$('#sig_in').next().html(msg);
$('#sig_in').next().css("color", "red");
}
},
error : function(e) {
alert("系统异常");
}
});
$('#password').val("");
}
login(); // 这是调用login()函数,是一个Statement;解释器遇到语句是会运行它的。
在上述例子中,像登录方法这个普通的函数声明function login(){};
默认是不会执行的。如果直接这样写成function login(){}()
这种形式,其实解释器是会报错的,因为这种写法是错误的语法。
IIFE
(立即执行函数)函数的调用方式通常是将函数表达式
、它的调用操作符
、分组操作符
放到一个括号内
,来告诉解释器这里有一个需要立即执行的函数。否则通常情况下,解析器遇到一个function
关键字,都会把它当做是一个函数声明,而不是函数表达式。
如下几种写法都是可以的:
(function login(){/*...*/}());
(function login(){/*...*/})();
!function login() {/*...*/}();
+function login() {/*...*/}();
-function login() {/*...*/}();
~function login() {/*...*/}();
以圆括号开头,引擎就会认为后面跟的是一个表示式,而不是函数定义语句
在需要表达式的场景下,就不需要用括号括起来了:
void function(){/*...*/}();
var login= function(){/*...*/}();
true && function () { /*...*/ }();
0, function () { /*...*/ }();
void
声明了不需要返回值,第二个则将IIFE函数的返回值赋给了foo
。第三、第四个都是明确需要表达式的场景,所以解析器会认识这种写法。
对于IIFE
函数,也可以给它们传入参数,例如:
(function login(arg1,arg2,...){...}(param1,param2,...));
对于常见的(function($){...})(jQuery)
;即是将实参jQuery
传入函数function($){}
,通过形参$
接收。
上述函数中,最开始的那个括号,可能会由于js中自动分号插入机制而引发问题。例如:
a = b + c
;(function () {
// code
})();
如果没有第二行的分号,那么该处有可能被解析为c()而开始执行。所以有的时候,可能会看到这样的写法:;(function login(){/*...*/}())
,前边的分号可以认为是防御型分号。
其实 $(function(){/*...*/});
是$(document).ready(function(){/*...*/})
的简写形式,是在DOM
加载完成后执行的回调函数
,并且只会执行一次
。
$( document ).ready(function() {
console.log( "ready!" );
});
等价于:
$(function() {
console.log( "ready!" );
});
上面两种写法起到的效果完全一样,效果都是等同的。
在一个页面中,当有多个当DOM
加载渲染完成时就开始执行的回调函数$(function(){/*...*/});
时,会根据js
的排列顺序依次执行该匿名函数。
例如:
login.html
<html>
<head>head>
<body>
<span>This page is shown to understand '$(document).ready()' in jQuery. <br /><span>
<p>
If you see this line, it means DOM hierarchy has been loaded. NOW loading jQuery from server and execute JS...<br /><br />
p>
<script src="http://code.jquery.com/jquery-latest.js">script>
<script src="index1.js">script>
<script src="index2.js">script>
body>
html>
index1.js
$(function(){
$(document.body).append("$(document).ready()1 is now been executed!!!
");
});
index2.js
$(function(){
$(document.body).append("$(document).ready()2 is now been executed!!!
");
});
最后可以看到页面输出如下:
This page is shown to understand '$(document).ready()' in jQuery.
If you see this line, it means DOM hierarchy has been loaded. NOW loading jQuery from server and execute JS...
$(document).ready()1 is now been executed!!!
$(document).ready()2 is now been executed!!!
通过上述例子,证实了前面提出的猜想,在一个页面中有多个$(function(){/*...*/});
函数时,会根据js
的排列顺序依次执行。