一件我很固执和坚持的事就是,写代码时分离出来一个可定制的配置对象。我现在写的脚本一般都长这样:
var module =function(){
config ={
CSS:{
classes:{
hover:'hover',
active:'current',
jsEnabled:'js'},
ids:{
container:'maincontainer'}
},
timeout:2000,
userID:'chrisheilmann'
};
function init(){
};
// ... more methods and other code ...
return{
init:init
};}();
module.init();
这样的好处十分明显:
当实施者修改时,不必满屏幕找代码,这里明显的表明:改这里吧。这允许更多的开发者用你的代码。你显示一个地方可以重写的地方给实施者。
比如你可以通过定义html文档的ID和CSS类名来应用到元素。
配置对象的属性都是字符串可以更好的定位和加速脚本。
有时你不是初始化,而想更改配置项,最简单的方式就是让配置对象暴露出来:
var module =function(){// configuration, change things herevar config ={
CSS:{
classes:{
hover:'hover',
active:'current',
jsEnabled:'js'},
ids:{
container:'maincontainer'}},
timeout:2000,
userID:'chrisheilmann'};
// start of main code
function init(){
};
// ... more methods and other code ...
// make init and config a public method
return{
init:init,
config:config
};}();
在这种情况下你可以这样在用init之前重写你的配置项属性:
module.config.CSS.ids.container='header';
module.config.userID='alanwhite';
module.init();
一种更简便的方式是将一个对象作为一个参数在init()中,你可以通过检查这个对象遍历递归它的属性匹配配置对象
var module =function(){// configuration, change things herevar config ={
CSS:{
classes:{
hover:'hover',
active:'current',
jsEnabled:'js'},
ids:{
container:'maincontainer'}},
timeout:2000,
userID:'chrisheilmann'};
// start of main code
function init(){
// check if the first argument is an objectvar a =arguments;
if(isObj(a[0])){
var cfg = a[0];
for(var i in cfg){
setConfig(config,i,cfg[i]);
}
}
};
function setConfig(o,p,v){
// loop through all the properties of he object
for(var i in o){
if(isObj(o[i])){
setConfig(o[i],p,v);
}else{
if(i === p){
o[p]= v;
}
}
}
};
// tests if a parameter is an object (and not an array)
function isObj(o){
return(typeof o ==='object'&&typeof o.splice!=='function');
}
// ... more methods and other code ...
// make init a public method
return{
init:init
};}();
module.init({
container:'header','timeout':1000});
当配置对象的所有属性是独特的时这段代码运行的很顺畅.但当属性是嵌套的,上下嵌套层级名字一样是,会失败.为了让这种情况可行.我们可以提供一个选项,发送一个字符串,描述属性的路径.然后就会变的凌乱,我们需要用eval()去解析字符串,确定返回值是正确的格式,所有这些看起来是这样的:
var module =function(){// configuration, change things herevar config ={
CSS:{
classes:{
hover:'hover',
active:'current',
jsEnabled:'js'},
ids:{
container:'maincontainer'}},
timeout:2000,
userID:'chrisheilmann'};
// start of main code
function init(){
if(isObj(arguments[0])){
var cfg = arguments[0];
for(var i in cfg){
if(i.indexOf('.')!==-1){
var str ='["'+ i.replace(/\./g,'"]["')+'"]';
var val = getValue(cfg[i]);
eval('config'+ str +'='+ val);
}else{
setConfig(config,i,cfg[i]);
}
}
}
};
function setConfig(o,p,v){
for(var i in o){
if(isObj(o[i])){
setConfig(o[i],p,v);
}else{
if(i === p){
o[p]= v;
};
}
}
};
function isObj(o){
return(typeof o ==='object'&&typeof o.splice!=='function');
};
function getValue(v){
switch(typeof v){
case'string':return"'"+v+"'";break;
case'number':return v;break;
case'object':
if(typeof v.splice==='function'){
return'['+ v +']';
}else{
return'{'+ v +'}';
}
break;
case NaN:break;
};
};
// ... more methods and other code ...
// make init a public method
return{
init:init
};}();
module.init({'container':'header','CSS.classes.active':'now','timeout':1000});
为了更有可读性,让我们封装一下:
var module =function(){// configuration, change things herevar config ={
CSS:{
classes:{
hover:'hover',
active:'current',
jsEnabled:'js'},
ids:{
container:'maincontainer'}},
timeout:2000,
userID:'chrisheilmann'};
// start of main code
function init(){
console.log(config);
};
// ... more methods and other code ...
// Configuration changes
var changeConfig =function(){
functionset(o){
var reg =/\./g;
if(isObj(o)){
for(var i in o){
if(i.indexOf('.')!==-1){
var str ='["'+ i.replace(reg,'"]["')+'"]';
var val = getValue(o[i]);
eval('config'+ str +'='+ val);
}else{
findProperty(config,i,o[i]);
}
}
}
};
function findProperty(o,p,v){
for(var i in o){
if(isObj(o[i])){
findProperty(o[i],p,v);
}else{
if(i === p){
o[p]= v;
};
}
}
};
function isObj(o){
return(typeof o ==='object'&&typeof o.splice!=='function');
};
function getValue(v){
switch(typeof v){
case'string':return"'"+v+"'";break;
case'number':return v;break;
case'object':
if(typeof v.splice==='function'){ return'['+v+']';} else{return'{'+v+'}';}break;
caseNaN:break;
};
};
return{
set:set};
}();
// make init a public method
return{
init:init
};}();
module.init({'container':'header','CSS.classes.active':'now','timeout':1000});