Reputation: 1517
I would like to allow my user to execute a series of functions while applying a certain object as the environment. For example, I have some object which contains data and operations.
environment = {
member1 = 0
operation1 = ->
member1 += 1
}
I want to allow the user to send commands into the environment as if it were the global object, without referencing it with this
i.e.
environment.evaluate("operation1()")
It would also be nice if I could create operations outside the environment, but allow them to be sent into this hypothetical 'evaluate' function.
Is it possible to build something like this? Does it have native javascript support?
Upvotes: 0
Views: 248
Reputation: 6282
changing now. just realized what you needed
this calls a member of the private methods object.
// create a closure which is your environment using the module pattern
var environment = (function() {
// local variables to the environment
var member1 = 0;
// public interface
var methods = {
operation: function(num) {
return member1 += (num || 1);
},
evaluate: function evaluate(name) {
var rest = Array.prototype.slice.call(arguments, 1);
// call your function by name passing in the rest of the arguments
return typeof methods[name] === 'function' && methods[name].apply(this, rest);
}
}
return methods;
})();
console.assert(typeof member1 === 'undefined', 'member1 is out of scope');
console.assert((environment.evaluate("operation", 2) === 2), 'member1 === 2');
console.log(environment.evaluate("operation", 2));
<script src="http://codepen.io/synthet1c/pen/WrQapG.js"></script>
old answer
I just noticed you requested coffee script. This is javascript you could use. I have never used coffee script but it shouldn't be hard to change to coffee and coffee compiles to js anyway.
The key is having a closure around the entire environment and using eval
to modify the internal state. You are really better off having specific getters and setters to limit the api to just the things you allow, otherwise the end user has access to modify anything in the scope, so nothing is private.
// create a closure which is your environment using the module pattern
var environment = (function() {
// local variables to the environment
var member1 = 0;
// return the public interface
return {
// this function evals the code in the context of the environment
evaluate: function evaluate(operation) {
// eval a closure so anything you put in there is run and returned to the outer environment
return eval('(function(){ return ' + operation + '})()');
}
}
})();
console.assert( typeof member1 === 'undefined', 'is member1 out of scope' );
console.log( environment.evaluate("++member1") );
<!-- begin snippet: js hide: false -->
<script src="http://codepen.io/synthet1c/pen/WrQapG.js"></script>
var es6environment = (function() {
let member1 = 0;
const methods = {
operation: (num = 1) => member += num,
evaluate: (name, ...rest) => typeof methods[name] === 'function' && methods[name].apply(this, rest);
}
return methods;
})();
<script src="http://codepen.io/synthet1c/pen/WrQapG.js"></script>
Upvotes: 3