js中自執行函式的怪異行為研究

龍旗飄揚的艦隊發表於2019-02-18

立即呼叫函式表示式

  • 給函式體加大括號,在有變數宣告的情形下,沒有任何區別
  • 但是,如果只是【自動執行】的情形下,就會不同
  • 因為,一個匿名函式,不賦值或不加小括號,是不能自動執行的
//以下情形並無差別
var count100 = function getCount100(){ return(100) }();//100
var count200 = (function getCount200(){ return(200) })();//200,加大括號和count100沒有區別
var count = (function getCount(n){ return(n) })(300);//300,傳參的情形
//不賦組變數,僅僅自動執行
(function aaa(){console.log("aaa")})();// aaa
console.log(aaa);//aaa is not defined
//一個匿名函式,不加大括號,是不能自動執行的
function bbb(){console.log("bbb")}();//Unexpected token )
複製程式碼
  • ==實際上【自執行函式表示式】可以有很多複雜的情形==,比如下邊的複雜例子
//函式宣告置於小括號中,沒有自執行
( function fn(){console.log("aaa");return "bbb"} );
console.log("fn res is " + fn);// fn is not defined

//函式宣告置於小括號中,且自執行
( function fn(){console.log("aaa");return "bbb"}() );//輸出aaa
console.log("fn res is " + fn);// fn is not defined

//函式宣告置於小括號中,且自執行,注意,負責執行的一對小括號移到了外部
( function fn(){console.log("aaa");return "bbb"} )();//輸出aaa
console.log("fn res is " + fn);// fn is not defined

//函式宣告置於小括號中,函式未執行但將其賦值給fn
( fn = function aaa(){console.log("aaa");return "bbb"} )
console.log("fn res is " + fn());//fn res is bbb

//函式宣告置於小括號中,函式執行,並且將其賦值給fn
( fn = function aaa(){console.log("aaa");return "bbb"}() );//輸出aaa
console.log("fn res is " + fn);//fn res is bbb

//函式宣告置於小括號中,將其賦值給fn,並且在外部執行之(注意末尾小括號位置)
( fn = function aaa(){console.log("aaa");return "bbb"} )();//輸出aaa
console.log("fn res is " + fn());//再次輸出aaa,並輸出fn res is bbb

// 匿名函式在自執行,注意末尾小括號位置
( function(){console.log("aaa");return "bbb"} )();//輸出aaa

// 匿名函式在自執行,可見和上邊的例子效果一致
( function(){console.log("aaa");return "bbb"}() );//輸出aaa

//在括號外賦值的函式表示式,例一。以下三例的結果是一致的
var fn = function aaa(){return "bbb"}();
console.log("fn is res " + fn);//fn is res bbb
//例二
var fn = (function aaa(){return "bbb"})();
console.log("fn is res " + fn);//fn is res bbb
//例三
var fn = (function(){return "bbb"})();
console.log("fn is res " + fn);//fn is res bbb
-------

//正常的函式,注意fn的name屬性自動設定為fn
function fn(){return "bbb"};
console.log(fn.name);//fn
console.log("fn is res " + fn());//fn is res bbb
//函式表示式,注意fn的name屬性是fn
var fn = function(){return "bbb"};
console.log(fn.name);//fn
console.log("fn is res " + fn());//fn is res bbb
//函式表示式,注意fn的name屬性是aaa
var fn = function aaa(){return "bbb"};
console.log(fn.name);//aaa
console.log("fn is res " + fn());//fn is res bbb

複製程式碼

對於如此多的不同情形,可以總結如下:

  • 在不賦值的情形下,在小括號中的函式或者函式表示式,被阻止宣告為一個全域性的變數,同時其內部是可執行的
  • 但如果其在小括號中,被賦值給了某一變數,那麼該函式或者函式表示式就會被曝露出去,可以在外部呼叫
  • 函式表示式在賦值給一個變數時,該變數會擁有一個name屬性,它的值取決於函式表示式是否為匿名函式
  • 如果為匿名函式,則變數的name屬性值為自身,如果為具名函式,則變數的name屬性值為具名函式的name值
  • 影響表示式執行的末尾的一對小括號,對詞法上的影響很小
  • 即,影響函式表示式的因素,由大到小是: 賦值與否 => 匿名與否 => 何時執行

相關文章