虽然下面的示例利用了 ExtJS,但可以很容易地推断到另一个框架。我是抽象和数据隐藏的粉丝(以及一般的 OO);有没有其他人隐藏数据和成员/函数,或者您认为这种尝试是矫枉过正?
(注意:我坚信 DOM ID 几乎不应该被硬编码。而且,虽然我使用典型类的公共(public)方法的原型(prototype),但您会注意到下面在原型(prototype)之外创建的公共(public)函数。)
这个笔记很有趣http://yuiblog.com/blog/2007/06/12/module-pattern/
Ext.ns('Foo.Bar');
/**
* Foo.Bar.MainToolbar (singleton)
*/
Foo.Bar.MainToolbar = (function()
{
// Temporary, private class used to create and return an object - a singleton
var toolbarClass = Ext.extend( Ext.Container,
{
/**
* constructor (public)
*/
constructor: function( config )
{
config = config || {};
// PRIVATE MEMBER DATA ========================================
// Need IDs for animation anchors
var accountId = Ext.id( null, 'ls-accountDiv-');
var faqId = Ext.id( null, 'ls-faqDiv-');
var logoutId = Ext.id( null, 'ls-logoutDiv-');
var loginId = Ext.id( null, 'ls-loginDiv-');
var rulesId = Ext.id( null, 'ls-rulesDiv-');
var itemCls =
'color: white; cursor: pointer; font-weight: bold; ' +
'font-family:Helvetica,Arial,Verdana,Lucida Sans Unicode,Sans-serif;';
// PUBLIC METHODS *********************************************
/**
* userLogin (public) -
*/
this.userLogin = function( userName, password )
{
// Update title bar
Ext.fly(accountId).update( userName );
Ext.fly(loginId).hide(true);
Ext.fly(logoutId).show(true);
};
// PRIVATE METHODS ********************************************
/**
* handleFaqClick (private) - handler for click on FAQ
*/
var handleFaqClick = function( event )
{
var dialogMsg = '<div style="text-align: leftblah, blah</div>';
Ext.Msg.show({
title: 'FAQ',
modal: true,
msg: dialogMsg,
animEl: faqId,
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.QUESTION,
minWidth: '700'
});
};
/**
* handleLogoutClick (private) - handler for click on logout
*/
var handleLogoutClick = function( event )
{
Ext.fly(accountId).update('');
Ext.fly(logoutId).hide(true);
Ext.fly(loginId).show(true);
};
/**
* handleRulesClick (private) - handler for click on RULES
*/
var handleRulesClick = function( event )
{
var dialogMsg =
'<div style="text-align: left;"><br/><b>blah, blah</div>';
Ext.Msg.show({
title: 'Rules',
modal: true,
msg: dialogMsg,
animEl: rulesId,
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.INFO,
minWidth: '700'
});
};
// CONSTRUCTOR ===============================================
// Some parameters (possibly) offered by the user are ignored
config.id = Ext.id( null, 'ls-mainToolbar-');
config.layout = 'absolute';
config.layoutConfig = {};
config.height = 38;
config.width = 968;
config.items = [
{
id: Ext.id( null, 'ls-mainToolbar-'),
xtype: 'box', x: 25, y: 0, height: 36,
autoEl: { tag: 'img', src: './images/top_toolbar.png' }
},{
id: Ext.id( null, 'ls-logo-'),
xtype: 'box',
x: 70, y: 8, height: 22, width: 200,
autoEl: { style: itemCls, html: 'Foo Bar' }
},{
id: accountId,
xtype: 'box',
x: 470, y: 8, height: 22, width: 200,
autoEl: { style: itemCls + ' text-align: right;', html: ' ' }
},{
id: logoutId,
xtype: 'box', x: 730, y: 8, height: 22, width: 36,
autoEl: {style: itemCls + ' visibility: hidden;', html: 'logout'},
listeners:
{ render:
function( cmp ){
cmp.getEl().addListener('click',
handleLogoutClick.createDelegate(this))
}.createDelegate(this)
}
},{
id: loginId,
xtype: 'box', x: 730, y: 8, height: 22, width: 36,
autoEl: { style: itemCls, html: 'login' },
listeners:
{ render:
function( cmp ){
cmp.getEl().addListener('click',
Foo.Bar.LoginDialog.show.createDelegate(
Foo.Bar.LoginDialog, [Ext.emptyFn]))
}
}
},{
id: rulesId,
xtype: 'box', x: 800, y: 8, height: 22, width: 36,
autoEl: { style: itemCls, html: 'rules'},
listeners:
{ render:
function( cmp ){
cmp.getEl().addListener( 'click',
handleRulesClick.createDelegate(this) )
}.createDelegate(this)
}
},{
id: faqId,
xtype: 'box', x: 860, y: 8, height: 22, width: 26,
autoEl: { style: itemCls, html: 'faq'},
listeners:
{ render:
function( cmp ){
cmp.getEl().addListener( 'click',
handleFaqClick.createDelegate(this) )
}.createDelegate(this)
}
}];
toolbarClass.superclass.constructor.apply( this, [config] );
Foo.Bar.LoginDialog.addListener(
Foo.Bar.LoginDialog.LOGIN_SUCCESSFUL_EVENT(),
this.userLogin.createDelegate(this));
}
});
return new toolbarClass();
})();
最佳答案
小心地在 JavaScript 中隐藏数据通常是一种矫枉过正,但这可能也是一个非常好的主意,尤其是当您正在创建一个库并希望使用者使用库的公共(public) API 而不是乱搞内部结构时(很多像这样富有想象力的人)。
在 JavaScript 中,隐藏数据/方法的模式通常是创建一个闭包,您可以在其中拥有所有私有(private)内容,并让您的公共(public) API 方法可以访问该闭包。
简单的例子:
var API = (function() {
// internal stuff goes in here
// ...
// some public methods i'll expose later
// all have access to the internals since they're inside the closure
function method1() { ... }
function method2() { ... }
var somevar;
return {
public_method1: method1,
public_method2: method2,
public_var: somevar,
};
})();
// use the API:
API.public_method1();
关于javascript - JS中的单例模式和抽象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1783317/