Created
July 30, 2009 14:42
-
-
Save furf/158722 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Transmogrifier (map) { | |
var EMPTY = '', | |
SOURCE = 's', | |
TARGET = 't', | |
DOT = '.', | |
EQUALS = '=', | |
OBJECT = '{}', | |
BREAK = ';\n', | |
NUMERIC_INDEX_REGEXP = /\.(\d+)/g, | |
modifiers = []; | |
function makeSource (map /*, root */) { | |
var root = arguments[1] || EMPTY, | |
rootDot = (root !== EMPTY) ? root + DOT : EMPTY, | |
src = [], | |
prop, | |
val, | |
i; | |
// Open function | |
if (root === EMPTY) { | |
src.push('var ', TARGET, EQUALS, OBJECT, BREAK); | |
// Render nested object | |
} else { | |
src.push(TARGET, DOT, root, EQUALS, OBJECT, BREAK); | |
} | |
// Iterate map properties | |
for (prop in map) { | |
if (map.hasOwnProperty(prop)) { | |
val = map[prop]; | |
// Traverse nested objects | |
if (typeof val === 'object') { | |
src.push(makeSource(val, prop)); | |
// Render dot-delimited properties and modifiers | |
} else { | |
// Render left-hand assignment | |
src.push(TARGET, DOT, rootDot, prop, EQUALS); | |
// Render modifier | |
if (typeof val === 'function') { | |
modifiers[prop] = val; | |
src.push('this.modifiers.', prop, '(', SOURCE, ')', BREAK); | |
// Render dot-delimited property as gated assignment | |
} else { | |
val = val.split(DOT); | |
for (i = val.length - 1; i >= 0; --i) { | |
val[i] = SOURCE + DOT + val.slice(0, i + 1).join(DOT); | |
} | |
src.push(val.join('&&').replace(NUMERIC_INDEX_REGEXP, '[$1]'), BREAK); | |
} | |
} | |
} | |
} | |
// Close function | |
if (root === EMPTY) { | |
src.push('return ', TARGET, BREAK); | |
} | |
return src.join(EMPTY); | |
} | |
this.transmogrify = new Function(SOURCE, makeSource(map)); | |
this.modifiers = modifiers; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Transmogrifier(a){var b="",j="s",e="t",g=".",i="=",c="{}",k=";\n",d=/\.(\d+)/g,h=[];function f(o){var m=arguments[1]||b,l=(m!==b)?m+g:b,q=[],r,p,n;if(m===b){q.push("var ",e,i,c,k);}else{q.push(e,g,m,i,c,k);}for(r in o){if(o.hasOwnProperty(r)){p=o[r];if(typeof p==="object"){q.push(f(p,r));}else{q.push(e,g,l,r,i);if(typeof p==="function"){h[r]=p;q.push("this.modifiers.",r,"(",j,")",k);}else{p=p.split(g);for(n=p.length-1;n>=0;--n){p[n]=j+g+p.slice(0,n+1).join(g);}q.push(p.join("&&").replace(d,"[$1]"),k);}}}}if(m===b){q.push("return ",e,k);}return q.join(b);}this.transmogrify=new Function(j,f(a));this.modifiers=h;} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var contactMap = { | |
firstName: 'invoice.billing.fname', | |
lastName: 'invoice.billing.lname', | |
billingAddress: { | |
undefined: 'foo.bar', | |
job: 'invoice.billing.jobs.2.name', | |
address: function (obj) { | |
var b = obj.invoice.billing; | |
return b.city + ', ' + | |
b.state + ' ' + | |
b.country; | |
} | |
}, | |
getFullName: function (obj) { | |
return function getFullName () { | |
return this.firstName + ' ' + this.lastName; | |
}; | |
} | |
}, | |
contactTransmogrifier = new Transmogrifier(contactMap), | |
contact = { | |
invoice: { | |
billing: { | |
fname: 'Dave', | |
lname: 'Furfero', | |
city: 'Harlem', | |
state: 'NY', | |
country: 'USA', | |
jobs: [ | |
{name:'Live Nation'}, | |
{name:'Time, Inc.'}, | |
{name:'MLB'} | |
] | |
} | |
} | |
}; | |
console.group('source'); | |
console.log(contactTransmogrifier.transmogrify.toString()); | |
console.groupEnd('source'); | |
console.group('input'); | |
console.dir(contact); | |
console.groupEnd('input'); | |
console.group('output'); | |
console.dir(contactTransmogrifier.transmogrify(contact)); | |
console.groupEnd('output'); | |
console.group('time'); | |
var r = stress(function contactTransmogrifierTest() { | |
contactTransmogrifier.transmogrify(contact); | |
}); // stress | |
console.log(r.each, 'ms'); | |
console.groupEnd('time'); | |
var p = contactTransmogrifier.transmogrify(contact); | |
console.log(p.getFullName()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment