您更喜欢哪一个,哪个是专业人士?一个人在另一个人身上?
我个人认为单身人士难以阅读和维护,很多情境变化( this ),总是以var self = this
(或某些代理人,如$.proxy
)缓存正确的上下文结束我将永远有一个全局变量(单例),而在第二种方法中,如果模块不需要公开任何API,我可以避免创建全局变量。
简单示例:
(用户点击"添加到购物车",一些ajax被触发,成功html(通知)被创建)
的 HTML
<div class="cart">
<a href="#" data-product-id="200"> Add to cart </a>
</div>
模块模式
根据定义,不是真正的模块模式,因为我没有从中返回任何内容,单击处理程序可以通过闭包访问外部作用域。
;(function(window, $, undefined) {
function constructHtml(data) {...}
function addToCart(product_id, quantity) {
...
$.ajax({
...
success: function(data) { constructHtml(data); }
});
}
$(function() {
var $addBtn = $('div.cart a');
var productId = $addBtn.data('product-id');
$addBtn.click(function(e) {
e.preventDefault();
addToCart(productId);
});
});
})(this, jQuery);
Singleton - Object literal(相同示例)
var Cart = {
settings: {
$addBtn: $('div.cart a'),
productId: $('div.cart a').data('product-id')
},
init: function() {
this.bindUiActions();
},
bindUiActions: function() {
var self = this;
this.settings.$addBtn.click(function(e) {
e.preventDefault();
self.addToCart(self.settings.productId);
});
},
addToCart: function(product_id, quantity) {
...
var self = this;
$.ajax({
...
success: function(data) {
self.constructHtml(data);
}
});
},
constructHtml: function(data) {...}
};
Cart.init();
答案 0 :(得分:1)
虽然Singleton vs. Module Pattern可以是一个合法的问题,但是你给出的例子,这个问题应该改写为Singleton vs IIFE,因为它不是模块模式本身,而是IIFE,模块模式被包裹在内,这样可以防止Cart
单例出现。即便如此,这也不是一个问题 - IIFE和Singleton可以一起使用。 IIFE的目的只是为了使东西远离全球范围。
所以......,您可以将您的单身代码打包成IIFE,如下所示
;(function(){
var Cart = {
settings: {
// Your code ...
};
Cart.init();
})();
在这种情况下,您将代码编写为Singleton,但将其包装在IIFE中,并且不使用全局范围。 IIFE完全独立于您选择编写和组织代码的方式。对于Singleton vs. Module Pattern问题,您需要一个不同的示例。
答案 1 :(得分:0)
IIFE(立即调用函数表达式):
(function() {
console.log('run this in your browser console')
})()
模块模式:
var module = (function () {
var privateScopeVar = 1 // scope of the IIF
// the 'this' context in this scope is the global object (e.g. window)
// returns literal object who's method's scopes are lexically bound
// to the IIF scope
return {
publicMethod: () => privateScopeVar // publicMethod scope can access IIF scope
}
})()
在EcmaScrip5中多次包含/导入时无法覆盖的Singleton Literal + Singleton Literal:
var singleInstance = { firstName: 'Greg' }
var singleInstance = singleInstance || { firstName: 'Greg' }
在EcmaScrip6中无法多次覆盖或初始化的Singleton Literal:
const singleInstance = {
firstName: 'Greg',
called: false,
init: () => {
if (!this.called) {
console.log('only once')
this.called = true
}
}
}
// of course singleInstance.called = false; singleInstance.init() is always possible
IIF内的单身人士(提供私人状态)
const singleton = (function () {
// IIF private scope ensures there is a single instance ever
var storedInstance
// Also some private state for the singleton instance as well
const firstName = 'Greg'
// literal object that holds constructor function
const Singleton = {
getInstance: () => {
if (!storedInstance) {
storedInstance= {
getName: () => firstName
}
}
return storedInstance
}
}
return Singleton
})()