前言
在傳統(tǒng)開發(fā)工程師眼里只泼,單例就是保證一個類只有一個實例,實現(xiàn)的方法一般是先判斷實例存在與否未妹,如果存在直接返回,如果不存在就創(chuàng)建了再返回空入,這就確保了一個類只有一個實例對象络它。在JavaScript里,單例作為一個命名空間提供者执庐,從全局命名空間里提供一個唯一的訪問點來訪問該對象
在JavaScript里,實現(xiàn)單例的方式有很多種导梆,其中最簡單的一個方式是使用對象字面量的方法轨淌,其字面量里可以包含大量的屬性和方法:
下面是我在 FIS從入門到放棄 這個筆記中使用的示例
//這個是一個典型的很簡單的單例模式的例子
var message = {
//init 是接收參數(shù)的
init: function() {
var me = this;
console.log('message init');
me.render();
me.bind();
},
//render 是負責 render頁面
render: function() {
var me = this;
me.btn = $('#btn');
},
//bind 是負責綁相應的元素
bind: function() {
var me = this;
//jQuery.proxy( function, context )
//function為執(zhí)行的函數(shù),content為函數(shù)的上下文this值會被設置成這個object對象
me.btn.on('click',$.proxy(me._go,this));
},
_go:function(e){
console.log(e.target);
}
}
//將方法導出 這個 module.exports 方法是從 layout.tpl 中引用的 mod.js 中來的
module.exports = message;
下面是我在公司項目中的首次嘗試
//這里用的是單例模式中最簡單的以字面量的形式進行書寫的
var XYQAJS = {
//將這個對象初始化
init: function () {
var _me = this;
_me.render();
_me.bind();
_me.imgslide();
},
//提供所有需要用到的操作元素
render: function () {
var _me = this;
_me.openAskBtn = $('#openAskBtn');
_me.closebtn = $('.conform').find('.cf_closebtn');
_me.QASearchBtn = $('#QASearchBtn');
},
//將所有的事件都放到這里綁定
bind: function () {
var _me = this;
//$.proxy(_me.openpopup, this) 返回的其實是 _me.openpopup() 這個函數(shù)的上下文
//【我要提問】彈窗切換
_me.openAskBtn.on('click', $.proxy(_me.openpopup, this));
_me.closebtn.on('click', $.proxy(_me.closepopup, this));
_me.QASearchBtn.on('click', $.proxy(_me.searchkeyword, this));
},
//右側(cè)活動輪播圖
imgslide:function(){
jQuery("#slideBox1").slide({ mainCell: ".bd ul", autoPlay: true, interTime: 3000, effect: "fold", switchLoad: "_src" });
},
//打開彈窗
openpopup: function () {
$('.conformbg,.conform').show();
},
//關閉彈窗
closepopup: function () {
$('.conformbg,.conform').hide();
},
//搜索關鍵詞
searchkeyword: function () {
var word = $('#keyword').val();
//提交數(shù)據(jù)
}
}
XYQAJS.init();
- 在瀏覽器的控制臺中輸出會發(fā)現(xiàn)看尼,將所有的東西都綁在了唯一的
XYQAJS
對象上
image.png
接著我又將上面的方法寫成可 new 可擴展递鹉、繼承的
//這里是使用的設計模式中的單例模式進行書寫的
var XYQACommon = (function(){
var _module;
if (_module) {
return _module;
}
_module = this;
//將這個對象初始化
this.init = function () {
var _me = this;
_me.render();
_me.bind();
_me.imgslide();
},
//提供所有需要用到的操作元素
this.render = function () {
var _me = this;
_me.openAskBtn = $('#openAskBtn');
_me.closebtn = $('.conform').find('.cf_closebtn');
_me.QASearchBtn = $('#QASearchBtn');
_me.listMoreBtn = $(".wbn_det").find(".morebtn");
},
//將所有的事件綁定都放到這里
this.bind = function () {
var _me = this;
//$.proxy(_me.openpopup, this) 返回的其實是 _me.openpopup() 這個函數(shù)的上下文
//【我要提問】彈窗切換
_me.openAskBtn.on('click', $.proxy(_me.openpopup, this));
_me.closebtn.on('click', $.proxy(_me.closepopup, this));
_me.QASearchBtn.on('click', $.proxy(_me.searchkeyword, this));
_me.listMoreBtn.on('click', $.proxy(_me.listMoreShow, this));
},
//右側(cè)活動輪播圖
this.imgslide = function () {
jQuery("#slideBox1").slide({ mainCell: ".bd ul", autoPlay: true, interTime: 3000, effect: "fold", switchLoad: "_src" });
},
//打開彈窗
this.openpopup = function () {
$('.conformbg,.conform').show();
},
//關閉彈窗
this.closepopup = function () {
$('.conformbg,.conform').hide();
},
//搜索關鍵詞
this.searchkeyword = function () {
var word = $('#keyword').val();
//提交數(shù)據(jù)
},
//詳情頁右側(cè) 發(fā)標公告 點擊下拉展示全部
this.listMoreShow = function () {
var _hide = $(this.listMoreBtn).siblings(".wbn_det_list").not(".active");
//console.log(_hide);
if (_hide.is(":hidden")) {
_hide.slideDown(500);
} else {
_hide.slideUp(500);
}
}
return _module;
});
$(function () {
var xyqaCommon = new XYQACommon();
xyqaCommon.init();
xyqaCommon.addFn = function () {
console.log(0);
}
console.log(xyqaCommon);
var xyqaCommon2 = new XYQACommon();
console.log(xyqaCommon2);
});
- 上面的寫法可以使得這個 XYQACommon 對象可 new 可擴展、繼承藏斩,可以清楚的看到 xyqaCommon 執(zhí)行 init 之后對象上多了那些在 render 時掛載的 jq 元素躏结,還有就是在下面擴展了 addFn 并沒有影響到宿主
image.png