I'm trying to make a way to add functions under a specific namespace (dpcom). This may be in dot notation depending on what the user did in their javascript file. So basically, what I want them to do is something like this:
dpcom.library('something.foo.funcName', function开发者_运维百科() {
// Code goes here.
})
They can then call their stuff later like:
dpcom.something.foo.funcName();
Which will execute the code they defined above. The code I want help with in making it better is here (it's using jQuery):
dpcom.library = function(name, func) {
root = dpcom;
objects = name.split('.');
lastElement = objects[objects.length - 1];
$(objects).each(function(idx, elem) {
if (elem == lastElement) {
root[elem] = func;
} else if (!root[elem]) {
root[elem] = {}
}
root = root[elem];
});
}
This should handle the possible dot notation and create objects inside of my namespace if they don't already exist (I don't want to overwrite any already declared objects).
The code I have above seems to work great, but I have a feeling I can make it better but my brain isn't telling me where... Anyone want to take a stab at it?
You should be able to do this in a slightly more appealing manner using shift():
dpcom.library = function(name, func) {
var root = dpcom,
objects = name.split('.'),
elem;
while (elem = objects.shift()) {
if (objects.length) {
if (!root[elem])
root[elem] = {};
root = root[elem];
}
else
root[elem] = func;
}
}
This way, you can ditch the jQuery requirement. Also, don't forget to explicitly declare your vars with the var keyword.
Depending on your definition of sexy code, you could also replace this block:
if (objects.length) {
if (!root[elem])
root[elem] = {};
root = root[elem];
}
with:
if (objects.length)
root = !root[elem] ? root[elem] = {} : root[elem];
Is this some kind of weird code-golf?
Try this, it might work...
dpcom.library = function(name, func) {
var p = name.split('.'), e, root = this;
while (e = p.shift()) root = root[e] = root[e] || (!p.length ? func : {});
}
Here's a stab at it
dpcom.library = function(name, func) {
var lastElement, root = dpcom, objects = name.split(/\./);
lastElement = objects[objects.length - 1];
$.each(objects, function(idx, elem) {
if (!root[elem]) {
if (elem == lastElement) {
root[elem] = func;
} else {
root[elem] = {}
root = root[elem];
}
}
});
}
EDIT:
I've found myself using jQuery's extend method for this. Check out the docs here.
Using the reduce method for Arrays,
dpcom.library = function(key, value) {
var objects = key.split('.');
var leaf = objects.pop();
var constructHierarchy = function(object, property) {
return (object[property] = object[property] || {});
};
objects.reduce(constructHierarchy, dpcom)[leaf] = value;
};
To increase the sexiness factor, make the second value generic and not just a function. It is already being done in all answers, but being explicit about it helps :)
dpcom.library('awesome.object', { foo: 'woah' });
Don't know if this is any sexier or more readable, but it doesn't need da Query and hasn't any global vars ;)
var dpcom = {'test': null, 'something': {}};
dpcom.library = function(name, func) {
for(var i = 0, node = this, names = name.split('.'), l = names.length; i < l; i++) {
node = node[names[i]] = ((i == l - 1) ? func : node[names[i]] || {});
}
};
dpcom.library('something.foo.funcName', function() {
// Code goes here.
});
Result:
{ test: null
, library: [Function]
, something: { foo: { funcName: [Function] } }
}
Check out YUI 2's namespace function:
YAHOO.namespace('myNS').funcName = function(){/* do something with arguments */};
精彩评论