Created
May 1, 2015 18:22
-
-
Save b-studios/25037fffae9d4754a553 to your computer and use it in GitHub Desktop.
JS Imports
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
<html><script> | |
// Library Stuff | |
function assert(b) { | |
if (!b) { throw "Assertion failed!"; } | |
} | |
// binds `this` of f to `obj` | |
function bind(f, obj) { | |
return function () { | |
return f.apply(obj, arguments); | |
} | |
} | |
// convert some array-like object to an array | |
function toArray(argsObj) { | |
return [].slice.apply(argsObj); | |
} | |
function locally(f) { return f(); } | |
// This shows standard JS behavior | |
var module = { | |
foo: function () { return this.bar; }, | |
bar: 42 | |
} | |
assert(module.foo() == 42) | |
with (module) { | |
assert(foo() == 42) | |
} | |
// ReferenceError: foo is not defined | |
// (function () { assert(foo() == 42)}).apply(module); | |
var m = Object.create(module); | |
m.bar = 43; | |
assert(m.foo() == 43) | |
var m2 = { | |
foo: bind(module.foo, module), | |
bar: 43 | |
} | |
assert(m2.foo() == 42) | |
function check(obj, name) { | |
if (obj[name] === undefined) { | |
throw '"' + name + '" not defined in "' + obj + '"'; | |
} | |
return obj; | |
} | |
function load(obj, name) { | |
var el = check(obj, name)[name]; | |
if (typeof el === "function") { | |
el = bind(el, obj); | |
} | |
return el; | |
} | |
// Just extracting members of objects to import them. | |
// (Before: Binding `this` to the original receiver) | |
locally(function () { | |
var foo = load(module, 'foo'), | |
bar = load(module, 'bar'); | |
assert(foo() == 42) | |
}) | |
// Using `with` for import, but checking before to avoid | |
// unexpected behavior. Explicitly binding `this` is not | |
// necessary. | |
with (check(module, 'foo')) { | |
assert(foo() == 42) | |
// this might be unexpected! | |
bar = 43 | |
assert(foo() == 43) | |
} | |
function safe(obj) { | |
var dummy = {}; | |
toArray(arguments).slice(1).forEach(function (key) { | |
var el = check(obj, key)[key]; | |
if (typeof el === "function") { | |
dummy[key] = bind(el, obj); | |
} else { | |
dummy[key] = el | |
} | |
}) | |
return dummy; | |
} | |
// Somewhat safe use of `with` | |
with (safe(module, 'foo')) { | |
bar = 43 | |
assert(foo(), 42) | |
} | |
function Module(obj) { | |
return { | |
load: function () { | |
var args = []; | |
toArray(arguments).forEach(function (key) { | |
var el = check(obj, key)[key]; | |
if (typeof el === "function") { | |
el = bind(el, obj); | |
} | |
args.push(el); | |
}); | |
return function (f) { | |
return f.apply(this, args); | |
} | |
} | |
} | |
} | |
// More JS idiomatic way (though more verbose) | |
Module(m).load('foo')(function (foo) { | |
assert(foo(), 42) | |
}) | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment