Last active
December 21, 2015 06:58
-
-
Save SimonRichardson/6267447 to your computer and use it in GitHub Desktop.
Proxies - in this instance `__noSuchMethod__` indirect invocation on a different method.
This is really powerful for wrapping native items (like array, object) and providing methods that point to libraries like underscore, squishy. This following unboxes (`extract`) the `Seq` to works on the array and then boxes the array back into a `Seq` so it…
This file contains hidden or 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
| /**Note: This works in Firefox Nightly but not in Chrome (shame on you!)**/ | |
| var s = { | |
| concat: function(a, b) { | |
| return a.concat(b); | |
| }, | |
| map: function(a, f) { | |
| var accum = [], | |
| total, | |
| i; | |
| for (i = 0, total = a.length; i < total; i++) { | |
| accum[i] = f(a[i]); | |
| } | |
| return accum; | |
| }, | |
| isArray: function(a) { | |
| if(Array.isArray) return Array.isArray(a); | |
| else return Object.prototype.toString.call(a) === "[object Array]"; | |
| }, | |
| extract: function(o) { | |
| return 'extract' in o ? o.extract() : o; | |
| } | |
| }; | |
| function Seq(v) { | |
| this.value = s.isArray(v) ? v : [].slice.call(arguments); | |
| this.extract = function() { | |
| return this.value; | |
| }; | |
| } | |
| Seq.create = function(v) { | |
| var value = s.isArray(v) ? v : [].slice.call(arguments); | |
| return new Proxy(new Seq(value), { | |
| get: function(obj, prop) { | |
| if (prop in obj) return obj[prop]; | |
| else if(!(prop in s)) throw new Error('NoSuchMethod ' + prop + ' on ' + s); | |
| return function() { | |
| var args = s.map([].slice.call(arguments), function(a) { | |
| return s.extract(a); | |
| }); | |
| return Seq.create(s[prop].apply(null, [s.extract(obj)].concat(args))); | |
| } | |
| } | |
| }); | |
| } | |
| var seq0 = Seq.create(1, 2, 3), | |
| seq1 = Seq.create(4, 5, 6), | |
| seq2 = Seq.create(7, 8, 9); | |
| console.log('Fin', seq0.concat(seq1).concat(seq2).map(x => x * 2)); // Seq(2, 4, 6, 8, 10, 12, 14, 16, 18) |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It's highly possible to make this a high level function so that it's possible to do this with any object.