前言
在傳統(tǒng)開發(fā)工程師眼里,單例就是保證一個(gè)類只有一個(gè)實(shí)例,實(shí)現(xiàn)的方法一般是先判斷實(shí)例存在與否,如果存在直接返回,如果不存在就創(chuàng)建了再返回,這就確保了一個(gè)類只有一個(gè)實(shí)例對(duì)象。在JavaScript里,單例作為一個(gè)命名空間提供者,從全局命名空間里提供一個(gè)唯一的訪問點(diǎn)來訪問該對(duì)象
在JavaScript里,實(shí)現(xiàn)單例的方式有很多種,其中最簡(jiǎn)單的一個(gè)方式是使用對(duì)象字面量的方法,其字面量里可以包含大量的屬性和方法:
下面是我在 FIS從入門到放棄 這個(gè)筆記中使用的示例
//這個(gè)是一個(gè)典型的很簡(jiǎn)單的單例模式的例子
var message = {
//init 是接收參數(shù)的
init: function() {
var me = this;
console.log('message init');
me.render();
me.bind();
},
//render 是負(fù)責(zé) render頁(yè)面
render: function() {
var me = this;
me.btn = $('#btn');
},
//bind 是負(fù)責(zé)綁相應(yīng)的元素
bind: function() {
var me = this;
//jQuery.proxy( function, context )
//function為執(zhí)行的函數(shù),content為函數(shù)的上下文this值會(huì)被設(shè)置成這個(gè)object對(duì)象
me.btn.on('click',$.proxy(me._go,this));
},
_go:function(e){
console.log(e.target);
}
}
//將方法導(dǎo)出 這個(gè) module.exports 方法是從 layout.tpl 中引用的 mod.js 中來的
module.exports = message;
下面是我在公司項(xiàng)目中的首次嘗試
//這里用的是單例模式中最簡(jiǎn)單的以字面量的形式進(jìn)行書寫的
var XYQAJS = {
//將這個(gè)對(duì)象初始化
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) 返回的其實(shí)是 _me.openpopup() 這個(gè)函數(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è)活動(dòng)輪播圖
imgslide:function(){
jQuery("#slideBox1").slide({ mainCell: ".bd ul", autoPlay: true, interTime: 3000, effect: "fold", switchLoad: "_src" });
},
//打開彈窗
openpopup: function () {
$('.conformbg,.conform').show();
},
//關(guān)閉彈窗
closepopup: function () {
$('.conformbg,.conform').hide();
},
//搜索關(guān)鍵詞
searchkeyword: function () {
var word = $('#keyword').val();
//提交數(shù)據(jù)
}
}
XYQAJS.init();
- 在瀏覽器的控制臺(tái)中輸出會(huì)發(fā)現(xiàn),將所有的東西都綁在了唯一的
XYQAJS對(duì)象上
image.png
接著我又將上面的方法寫成可 new 可擴(kuò)展、繼承的
//這里是使用的設(shè)計(jì)模式中的單例模式進(jìn)行書寫的
var XYQACommon = (function(){
var _module;
if (_module) {
return _module;
}
_module = this;
//將這個(gè)對(duì)象初始化
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) 返回的其實(shí)是 _me.openpopup() 這個(gè)函數(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è)活動(dòng)輪播圖
this.imgslide = function () {
jQuery("#slideBox1").slide({ mainCell: ".bd ul", autoPlay: true, interTime: 3000, effect: "fold", switchLoad: "_src" });
},
//打開彈窗
this.openpopup = function () {
$('.conformbg,.conform').show();
},
//關(guān)閉彈窗
this.closepopup = function () {
$('.conformbg,.conform').hide();
},
//搜索關(guān)鍵詞
this.searchkeyword = function () {
var word = $('#keyword').val();
//提交數(shù)據(jù)
},
//詳情頁(yè)右側(cè) 發(fā)標(biāo)公告 點(diǎn)擊下拉展示全部
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);
});
- 上面的寫法可以使得這個(gè) XYQACommon 對(duì)象可 new 可擴(kuò)展、繼承,可以清楚的看到 xyqaCommon 執(zhí)行 init 之后對(duì)象上多了那些在 render 時(shí)掛載的 jq 元素,還有就是在下面擴(kuò)展了 addFn 并沒有影響到宿主
image.png

