JS中(function(){}()),(function(){})(),$(function(){});之间的区别

一. (function(){}())与(function(){})()

2.1 立即执行函数

JS中,这两种写法,都是一种立即执行函数的写法,即IIFE (Immediately Invoked Function Expression)。这种函数在函数定义的地方就直接执行了。

关于立即执行函数,可参考:

  • 立即执行函数的 N 种写法
  • 立即调用的函数表达式(IIFE)

2.2 函数声明和调用

通常函数的声明和函数的调用写法分别如下:

  • 函数的声明:
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关键字,都会把它当做是一个函数声明,而不是函数表达式。

  • N种写法:

如下几种写法都是可以的:

(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(){});

其实 $(function(){/*...*/});$(document).ready(function(){/*...*/})的简写形式,是在DOM加载完成后执行的回调函数,并且只会执行一次

$( document ).ready(function() {
   console.log( "ready!" );
});   

等价于:

$(function() {
   console.log( "ready!" );
});

上面两种写法起到的效果完全一样,效果都是等同的。

三. 多个$(function(){});执行顺序

在一个页面中,当有多个当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的排列顺序依次执行。

你可能感兴趣的:(【36】JavaScript)