Skip to content

Instantly share code, notes, and snippets.

@AutoSponge
Last active October 10, 2015 22:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AutoSponge/3758975 to your computer and use it in GitHub Desktop.
Save AutoSponge/3758975 to your computer and use it in GitHub Desktop.
simple get
/**
* null-safe retrieval of objects and their property values from context
* @function get
* @param {String|String[]} path
* @param {Object} [obj=this]
* @return
*/
(function (HEAD) {
var depthCache = {};
var cache = {};
function getDepth(depth) {
if (!depthCache[depth]) {
var params = "";
var vars = " var _0 = this";
var body = false;
var h, i;
for (i = 0; i < depth; i += 1) {
params += i ? (", $" + i) : "$" + i;
vars += i ? (", _" + i) : "";
}
vars += ";\n";
for (h = i - 1; i > 0; i -= 1, h -= 1) {
if (!body) {
body = "_" + h + " === Object(_" + h + ") && ($" + h + " in _" + h + ") ? _" + h + "[$" + h + "]";
} else {
body = "(_" + i + " = _" + h + "[$" + h + "], _" + i + ") && " + body;
}
}
body = " return " + (!body ? "_0;" : body + " : void(0);");
depthCache[depth] = Function(params, vars + body);
}
return depthCache[depth];
}
function get(path, obj) {
var params = path ? path.split ? cache[path] || (cache[path] = path.split("."), cache[path]) : path : [];
return getDepth(params.length).apply(obj || this, params);
}
HEAD.get = get;
}(this));
//setup test objects
(function (HEAD) {
var paths = {};
HEAD.paths = paths;
HEAD.obj = (function (start, end) {
var i, next, obj, path, name;
next = obj = {};
path = "";
for (i = 0; i < (end - start); i += 1) {
name = String.fromCharCode(i + start);
next = next[name] = (i%3 < 2 ? {} : i%2 === 0 ? [] : function () {});
path += path.length ? "." + name : name;
paths[i + 1] = path;
}
return obj;
}(97, 123));
}(this));
//run tests
(function (tests, HEAD) {
var i = tests.length;
var test;
while (i--) {
test = tests[i];
if (test !== "ignore") {
switch (test[0]) {
case "type":
console.assert(typeof get(test[2], test[3]) === test[4], test[1]);
break;
case "instance":
console.assert(get(test[2], test[3]) instanceof test[4], test[1]);
break;
default:
console.assert(get(test[2], test[3]) === test[4], test[1]);
}
}
}
}([
//type message param1 param2 equals
["equals", "should get global from global", , , this],
["equals", "should get obj from global", "obj", , obj],
["equals", "should get obj from obj", null, obj, obj],
["equals", "should get obj from obj", , obj, obj],
["equals", "should get obj from obj at depth 0", paths[0], obj, obj],
["equals", "should get a from obj at depth 1", paths[1], obj, obj.a],
["equals", "should get z from obj at depth 26", paths[26], obj, obj.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z],
["equals", "should not get x from a at depth 2", paths[1] + ".x", obj, ],
["equals", "should not get x from a at depth 3", paths[1] + ".x.x", obj, ],
["instance","should return an array c from b", paths[3], obj, Array],
["equals", "should return length 0 from array c", paths[3] + ".length", obj, 0],
["equals", "should return length 0 from array c", ["a", "b", "c", "length"], obj, 0],
["type", "should return a function f from e", paths[6], obj, "function"],
["type", "should return a function apply from f", paths[6] + ".apply", obj, "function"],
["equals", "should return f.apply.length", paths[6] + ".apply.length", obj, 2],
["equals", "should get d from obj at depth 4", ["a", "b", "c", "d"], obj, obj.a.b.c.d],
"ignore"
], this));
function send(fn, args, obj) {
var f = fn;
var o = this || obj;
if (typeof fn === "string") {
f = get(fn, o);
}
return f.apply(o, args);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment