1. 什麼是自執行的匿名函數?
它是指形如這樣的函數: (function {// code})();
2. 疑問
為什麼(function {// code})();可以被執行, 而function {// code}();卻會報錯?
3. 分析
(1). 首先, 要清楚兩者的區別:
(function {// code})是運算式, function {// code}是函式宣告.
(2). 其次, js"先行編譯"的特點:
js在"先行編譯"階段, 會解釋函式宣告, 但卻會忽略表式.
(3). 當js執行到function() {//code}();時, 由於function() {//code}在"先行編譯"階段已經被解釋過, js會跳過function(){//code}, 試圖去執行();, 故會報錯;
當js執行到(function {// code})();時, 由於(function {// code})是運算式, js會去對它求解得到傳回值, 由於傳回值是一 個函數, 故而遇到();時, 便會被執行.
另外, 函數轉換為運算式的方法並不一定要靠分組操作符(),我們還可以用void操作符,~操作符,!操作符……
如:
!function(){ alert("另類的匿名函數自執行"); }();
佚名函數()() |
(()) |
(function() { alert('hello') })(); (function(v) { alert(v) })('hello'); |
(function() { alert('hello') }()); (function(v) { alert(v) }('hello')); |
有名函數()() |
(()) |
(function fn() { alert('hello') })(); |
(function fn() { alert('hello') }()); |
對象函數()() |
對象函數(()) |
({ init:function(){ alert('hello') } }).init(); |
({ init:function(){ alert('hello') } }.init()); |
對象內部() |
不可這樣調用 |
var foo = { fn: function (x) { return x % 2 != 0 ? 'yes' : 'no'; }(1)}; alert(foo.fn); // 'yes' |
var foo = { fn: function (x) { return x % 2 != 0 ? 'yes' : 'no'; }(1)}; alert(foo.fn());
|
對象+","+函數+() |
“對象”可以為如下,自己可試 |
1, function () { alert('anonymous function is called');}(); |
1、任一數字 2、特殊字元(!、~、- 、+) 3、void 4、true、false 當然這些也可以組合使用。 |
()應用,設計模式之單例模式 |
自訂對象 |
//()應用 var Singleton = (function () { function init() { /*這裡定義單例代碼*/ return { publicMethod: function () { alert('hello world'); } }; } return { getInstance: function () { return init(); } }; })(); /*調用公有的方法來擷取執行個體:*/ Singleton.getInstance().publicMethod(); |
var obj = {};(function (q) { q.publish = function (str) { alert(str); }} (obj)); //提交obj全域對象 obj.publish('hello');//hello (function (a) { a.publish = function (str) { alert(str); }} (window)); //window對象publish('hello'); |
著名應用執行個體:jQuery |
設計模式之迭代器模式 |
(function() {var jQuery = (function() { //構建jQuery對象 var jQuery = function() { //執行個體init() return new jQuery.fn.init(); }; jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function() { var match; }, jQuery: "1.7.1" }; // 合并 init()的屬性為jQuery.fn jQuery.fn.init.prototype = jQuery.fn; //返回jQuery return jQuery})();//定義jQuery全域對象window.jQuery = window.$ = jQuery;})(window); //應用執行個體alert($().jQuery);//1.7.1 |
var fn = (function () { var index = 0, data = [1, 2, 3, 4, 5], length = data.length; return { length: length, rewind: function () { index = 0; }, current: function () { return data[index]; } };} ());alert(fn.current()); |
根據參數選擇執行對象 |
|
var fn=(function(){ var obj={ i1:function(){ return 'a'; }(), i2:function(){ return 'b'; }() }; //json格式,可以無序排列 var json={"1":"i1","2":"i2"}; //array數組,有序排列 // var ar=["i11","i12"]; return { init:function(i){ return obj[json[i]]; } };})();alert(fn.init(1)); |
return { ini: function(X) { //聲明一個函數,名稱為ini X.__MSG_QS__ = {}; //為傳進來的對象添加屬性 X.on = C; //為傳進來的對象添加方法 X.dm = G; //為傳進來的對象添加方法 return X } } |
使用閉包: (function($) { // Code goes here })(jQuery);這是來自jQuery官方的外掛程式開發規範要求,使用這種編寫方式有什麼好處呢? a) 避免全域依賴。 b) 避免第三方破壞。 c) 相容jQuery操作符'$'和'jQuery ' 我們知道這段代碼在被解析時會形同如下代碼: var jq = function($) { // Code goes here }; jq(jQuery); |
|
|
|