Javascript: Configuration Pattern
Problem : A Javascript function needs few parameters to work with:
function kick(person, reason, amount) {
// kick the *person* with the *amount*, based on the *reason*
}
As there's no way to do function overloading in JS like how you do in Java, if it needs to be designed for easy future improvement (parameters adding), it can be written as:
/* Function Parameters pattern */
function kick() {
// kick the person as in *arguments[0]*, with the amount as in *arguments[1]*,
// based on the reason as in *arguments[2]*, with the strength as in *arguments[3]*
}
or
/* Object Configuration Pattern */
function kick(config) {
// kick the person as in *config.person*, with the amount as in *config.amount*,
// based on the reason as in *config.reason*, with the strength as in *config.strength*
}
I do know that Object Configuration Pattern allows augmentation for any default properties.
So, the question is: If I don't need to augment any properties with the parameters, is there any significant reason of using any one of the proposed solutions as opposed to the other?
Using an object has a few advantages:
1. The code is more readable
Consider the following two calls:
kick({user: u,
reason: "flood",
log: true,
rejoin: false,
timeout: 60000,
privmessage: true});
kick(u, "flood", true, false, 60000, true);
and imagine someone else reading the call. What is the first true
? Note also that yourself in a few month would be in the same exact position (not remembering what is the fourth parameter to kick
is very similar to not knowing it).
2. You can tunnel parameters
With the object approach you can pass a function a set of parameters that this function must use to call another function
function kickgroup(users, parms) {
for (var i=0; i<users.lenght; i++) {
var uparms = Object.create(parms);
uparms.user = users[i];
kick(uparms);
}
}
Note also that in the arguments
case you don't need to punish yourself by using arguments[x]
syntax. You can just declare the parameters and add them as the function evolves: any parameter that has not been passed will be set to undefined
(and if you need you can still access arguments.length
to distinguish if the caller explicitly passed your function undefined
).
You don't have to go strictly with any of the three. If you look at how jQuery does it, it examines the type and quantity and position of the parameters to figure out which overloaded flavor of the function is being used.
Suppose you had three flavors of kick()
, one that takes person, reason and amount and one that takes just person with reason and amount getting default values and one that takes a config object with at least a person on it. You could dynamically see which of the three options you had like this:
function kick(person, reason, amount) {
if (person.person) {
// must be an object as the first parameter
// extract the function parameters from that object
amount = person.amount;
reason = person.reason;
}
amount = amount || 5; // apply default value if parameter wasn't passed
reason = reason || "dislike"; // apply default value if parameter wasn't passed
// now you have person, reason and amount and can do normal processing
// you could have other parameters too
// you just have to be to tell which parameter is which by type and position
// process the kick here using person, reason and amount
}
JavaScript functions are signed by their name only.
Hence you can do:
function kick(x, reason, amount) {
if(reason && amount) {
// do stuff with x as person, reason and amount
}
else if(x) {
// do stuff with x as config
}
else {
// do stuff with no parameters
}
}
another solutions is to use the arguments variable which is an array that holds all parameters that passed to a function in javascript
function kick() {
alert(arguments.length);
}
链接地址: http://www.djcxy.com/p/51992.html
上一篇: 方法和函数重载在JavaScript和jQuery中
下一篇: Javascript:配置模式