1. 程式人生 > >JavaScript單例模式

JavaScript單例模式

全域性變數不是單例模式,但在JavaScript 開發中,我們經常會把全域性變數當成單例來使用。

使用名稱空間可以減少全域性變數的數量,以下程式碼是動態建立名稱空間:

var MyApp = {};
	MyApp.namespace = function( name ){
		var parts = name.split( '.' );
		var current = MyApp;
		for ( var i in parts ){
			if ( !current[ parts[ i ] ] ){
				current[ parts[ i ] ] = {};
			}
			current = current[ parts[ i ] ];


		}
	};
	MyApp.namespace( 'event' );
	MyApp.namespace( 'dom.style' );
	console.dir( MyApp );
	// 上述程式碼等價於:
	var MyApp = {
		event: {},
		dom: {
			style: {}
		}
	};

使用閉包封裝私有變數
這種方法把一些變數封裝在閉包的內部,只暴露一些介面跟外界通訊:

var user = (function(){
		var __name = 'sven',
		__age = 29;
		return {
			getUserInfo: function(){
				return __name + '-' + __age;
			}
		}
	})();
此處user物件包含多個函式,可以當成名稱空間來用。

通用的惰性單例:

<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>

<body>
    <button id="loginBtn">登入</button>
</body>
<script>
var getSingle = function(fn) {
    var result;
    return function() {
        return result || (result = fn.apply(this, arguments));
    }
};
var createLoginLayer = function() {
    var div = document.createElement('div');
    div.innerHTML = '我是登入浮窗';
    div.style.display = 'none';
    document.body.appendChild(div);
    return div;
};
var createSingleLoginLayer = getSingle(createLoginLayer);
document.getElementById('loginBtn').onclick = function() {
    var loginLayer = createSingleLoginLayer();
    loginLayer.style.display = 'block';
};

//下面我們再試試建立唯一的iframe 用於動態載入第三方頁面:
/*var createSingleIframe = getSingle( function(){
	var iframe = document.createElement ( 'iframe' );
	document.body.appendChild( iframe );
	return iframe;
});
document.getElementById( 'loginBtn' ).onclick = function(){
	var loginLayer = createSingleIframe();
	loginLayer.src = 'http://baidu.com';
};*/
</script>

</html>

這種單例模式的用途遠不止建立物件,比如我們通常渲染完頁面中的一個列表之後,接下來要給這個列表繫結click 事件,如果是通過ajax 動態往列表裡追加資料,在使用事件代理的前提下,click 事件實際上只需要在第一次渲染列表的時候被繫結一次,但是我們不想去判斷當前是否是第一次渲染列表,如果藉助於jQuery,我們通常選擇給節點繫結one 事件:

var bindEvent = function(){
		$( 'div' ).one( 'click', function(){
			alert ( 'click' );
		});
	};
	var render = function(){
		console.log( '開始渲染列表' );
		bindEvent();
	};
	render();

	render();
	render();

	var bindEvent = getSingle(function(){
		document.getElementById( 'div1' ).onclick = function(){
			alert ( 'click' );
		}
		return true;
	});
	var render = function(){
		console.log( '開始渲染列表' );
		bindEvent();
	};
	render();
	render();
	render();


總結:也就是說只要是想要哪個程式碼塊只執行一次就可以用這個惰性的getSingle函式。