Execute within an environment in javascript - javascript

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?

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>

Related

Is it possible to overwrite "global" variable via Webpack?

I am finding a way to make MathJax be able to run on a specific JS runtime with lots of limitations.
MathJax use global to access the MathJax object, and this is compiled by Webpack into the following snippet:
function (e, t) {
var n;
n = function () {
return this;
}();
try {
n = n || new Function("return this")()
} catch (e) {
"object" == typeof window && (n = window)
}
e.exports = n
}
The code above will try to assign the global this to e.exports, and the usage of global in MathJax's source code will be replaced with e.exports. However, in my JS runtime, window/global are not available, function () { return this; } returns undefined, new Function is restricted and only returns an empty object instead of a function.
My question is that, is it possible to configure Webpack to replace global with some other variable I specify (like limitedGlobal.someVar)?
For referrence, I found that the snippet above is defined in GlobalRuntimeModule.js, and I want to change its implementation.
Sure, please have a look at globalObject
Its default is global="window"
You can override it like this in your webpack configurations:
output: {
globalObject: 'this' // or limitedGlobal.someVar in your case
}

Does this way of defining JS objects have any purpose?

I'm maintaining some legacy code and I've noticed that the following pattern for defining objects is used:
var MyObject = {};
(function (root) {
root.myFunction = function (foo) {
//do something
};
})(MyObject);
Is there any purpose to this? Is it equivalent to just doing the following?
var MyObject = {
myFunction : function (foo) {
//do something
};
};
I'm not about to embark in a holy quest to refactor the whole codebase to my likings, but I'd really like to understand the reason behind that roundabout way of defining objects.
Thanks!
It's called the module pattern http://toddmotto.com/mastering-the-module-pattern/
The main reason is for you to create truly private methods and variables. In your case, it's not meaningful because it's not hiding any implementation details.
Here's an example where it makes sense to use the module pattern.
var MyNameSpace = {};
(function(ns){
// The value variable is hidden from the outside world
var value = 0;
// So is this function
function adder(num) {
return num + 1;
}
ns.getNext = function () {
return value = adder(value);
}
})(MyNameSpace);
var id = MyNameSpace.getNext(); // 1
var otherId = MyNameSpace.getNext(); // 2
var otherId = MyNameSpace.getNext(); // 3
Whereas if you just used a straight object, adder and value would become public
var MyNameSpace = {
value: 0,
adder: function(num) {
return num + 1;
},
getNext: function() {
return this.value = this.adder(this.value);
}
}
And you could break it by doing stuff like
MyNameSpace.getNext(); // 1
MyNameSpace.value = 0;
MyNameSpace.getNext(); // 1 again
delete MyNameSpace.adder;
MyNameSpace.getNext(); // error undefined is not a function
But with the module version
MyNameSpace.getNext(); // 1
// Is not affecting the internal value, it's creating a new property
MyNameSpace.value = 0;
MyNameSpace.getNext(); // 2, yessss
// Is not deleting anything
delete MyNameSpace.adder;
MyNameSpace.getNext(); // no problemo, outputs 3
The purpose is to limit accessibility of functions within the closure to help prevent other scripts from executing code on it. By wrapping it around a closure you are redefining the scope of execution for all code inside the closure and effectively creating a private scope. See this article for more info:
http://lupomontero.com/using-javascript-closures-to-create-private-scopes/
From the article:
One of the best known problems in JavaScript is its dependance on a
global scope, which basically means that any variables you declare
outside of a function live in the same name space: the ominous
window object. Because of the nature of web pages, many scripts from
different sources can (and will) run on the same page sharing a
common global scope and this can be a really really bad thing as it
can lead to name collisions (variables with the same names being
overwritten) and security issues. To minimise the problem we can use
JavaScript’s powerful closures to create private scopes where we can
be sure our variables are invisible to other scripts on the page.
Code:
var MyObject = {};
(function (root) {
function myPrivateFunction() {
return "I can only be called from within the closure";
}
root.myFunction = function (foo) {
//do something
};
myPrivateFunction(); // returns "I can only be called from within the closure"
})(MyObject);
myPrivateFunction(); // throws error - undefined is not a function
advantages:
maintains variables in private scope.
you can extend the functionality of the existing object.
performance is increased.
i think the above three simple points are just enough to follow those rules. And to keep it simple its nothing but writing inner functions.
In the particular case that you show, there is no meaningful difference, in terms of functionality or visibility.
It's likely that the original coder adopted this approach as a sort of template allowing him to define private variables that could be used in the definition of things like myFunction:
var MyObject = {};
(function(root) {
var seconds_per_day = 24 * 60 * 60; // <-- private variable
root.myFunction = function(foo) {
return seconds_per_day;
};
})(MyObject);
This avoids calculating seconds_per_day each time the function is called, while also keeping it from polluting the global scope.
However, there's nothing essentially different from that and just saying
var MyObject = function() {
var seconds_per_day = 24 * 60 * 60;
return {
myFunction: function(foo) {
return seconds_per_day;
}
};
}();
The original coder may have preferred to be able to add functions to the object using the declarative syntax of root.myFunction = function, rather than the object/property syntax of myFunction: function. But that difference is mainly a matter of preference.
However, the structure taken by the original coder has the advantage that properties/methods can be easily added elsewhere in the code:
var MyObject = {};
(function(root) {
var seconds_per_day = 24 * 60 * 60;
root.myFunction = function(foo) {
return seconds_per_day;
};
})(MyObject);
(function(root) {
var another_private_variable = Math.pi;
root.myFunction2 = function(bar) { };
})(MyObject);
Bottom line, there is no need to adopt this approach if you don't need to, but there is also no need to change it, since it works perfectly well and actually has some advantages.
First pattern can be used as a module which takes an object and returns that object with some modifications. In other words, you can define such modules as follows.
var module = function (root) {
root.myFunction = function (foo) {
//do something
};
}
And use it like:
var obj = {};
module(obj);
So an advantage could be the re-usability of this module for later uses.
In the first pattern, you can define a private scope to store your private stuff such as private properties and methods. For example, consider this snippet:
(function (root) {
// A private property
var factor = 3;
root.multiply = function (foo) {
return foo * factor;
};
})(MyObject);
This pattern can be used to add a method or property to all types of objects such as arrays, object literals, functions.
function sum(a, b) {
return a + b;
}
(function (root) {
// A private property
var factor = 3;
root.multiply = function (foo) {
return foo * factor;
};
})(sum);
console.log(sum(1, 2)); // 3
console.log(sum.multiply(4)); // 12
In my opinion the main advantage could be the second one (creating a private scope)
This pattern provides a scope in which you can define helper functions that are not visible in the global scope:
(function (root) {
function doFoo() { ... };
root.myFunction = function (foo) {
//do something
doFoo();
//do something else
};
})(MyObject);
doFoo is local to the anonymous function, it can't be referenced from outside.

Javascript module pattern import

I am trying to understand Javascript module patter, but I can't figure out the difference between parameters added to the anonymous function and parameters added at the end. So can someone please help me understand the difference between both? Thanks
Below is a module pattern example which implement both anon. function parameters (JQ, Yahoo) and module parameters shown at the end (JQuery, Yahoo).
var modularpattern = (function(JQ, Yahoo) {
var sum = 0 ;
return {
add:function() {
sum = sum + 1;
return sum;
},
reset:function() {
return sum = 0;
}
}
}(JQuery, Yahoo));
Logically your codes is equal to:
var func = function(JQ, Yahoo) { // Section 1
var sum = 0 ;
return {
add:function() {
sum = sum + 1;
return sum;
},
reset:function() {
return sum = 0;
}
}
}
var modularpattern = func(JQuery, Yahoo); // Section 2
So in section 1
JQ : A function local variable which is used as input argument
Yahoo : Exactly same as JQ
And in section 2 (In this section actually you invoke the function )
JQuery : An existing object in the global scope
Yahoo : Exactly same as JQuery
Why do developers implement like this:
All global objects is accessible inside function scopes but accessing to local variables is much faster than global variables. (This is called Localization)
I can't figure out the difference between parameters added to the anonymous function and parameters added at the end
The parameters added to the anonymous function are the names you're giving to these things inside your function
The parameters added at the end are the references to these objects
This means you can access a "safe(r)" reference, as it's less easily changed by other pieces of code
(function (bar) {
// use bar here, not foo as it's your protected reference
// but unless something else happens, bar === foo
}(foo);
Code using this pattern is good for several reasons
Keeps the namespace clean
If frameworks contain conflicts, gives you an "safe" environment to work in where you can use the default names
I had work with many realizations of Module Pattern, but this one is the best way:
(function(global) {
var somePrivate = 'foo';
function somePrivateMethod() {}
var myModule = function() {
// Your logic here
}
global.myModule = myModule;
})(this);

Function scope is lost in returned methods when strigifying/parsing js objects with JSON

I have such a bit crazy example, but it looks like a good exercise for those who are experts in javascript function scopes:
(function (global) {
// our module number one
var body = function () {
var someVar = 'some test text';
return {
method: function () {
return someVar; // this will undefined when call this method in second module
}
};
};
var f = new Function([' return (', body, ')();'].join(''));
global.r = f();
})(window);
(function (global) {
// our module two
var body = function () {
// dep variable is injected on the fly with `new Function`
dep.method(); // will throw `Reference Error: someVar is not defined`
};
// helper to propertly transform functions in JSON.stringify
function transformFuncs (key, val) {
if (typeof val === 'function') {
return val.toString().replace(/(\t|\n|\r)/gm, '').replace(/("|')/gm, '\\"');
}
return val;
}
// injecting our first module inside
var vars = ['var ', 'dep', ' = JSON.parse(\'', JSON.stringify(global.r, transformFuncs), '\', function (key, value) { if (value && typeof value === "string" && value.substr(0,8) == "function") { var startBody = value.indexOf("{") + 1; var endBody = value.lastIndexOf("}"); var startArgs = value.indexOf("(") + 1; var endArgs = value.indexOf(")"); return new Function(value.substring(startArgs, endArgs), value.substring(startBody, endBody)); } return value; });'].join('');
// as variable
var f2 = new Function([vars, ' return (', body, ')();'].join(''));
global.r2 = f2();
})(window);
If you'll run this code somewhere you'll see an exception thrown ReferenceError: someVar is not defined.
So basically what's happening here - we create some module and then trying to inject it inside another one as variable. Function that is used in JSON.parse to correctly get stringified functions looks like this (if you're curious):
function (key, value) {
if (value && typeof value === "string" && value.substr(0,8) == "function") {
var startBody = value.indexOf("{") + 1;
var endBody = value.lastIndexOf("}");
var startArgs = value.indexOf("(") + 1;
var endArgs = value.indexOf(")");
return new Function(value.substring(startArgs, endArgs), value.substring(startBody, endBody));
}
return value;
}
So.. the question is it possible to workaround such scope behavior? As I understand global.r is assigned with f result in one scope, but resulted object with method function is not saving the variable instance because while JSON parsing another scope is created for that function.
Any ideas?
P.S. Please don't ask why I need this :) just think about possible solutions. The main idea is to somehow inject module number one (look top body var) as variable inside second module (body var of second function) saving the original scope of methods that are returned.
Thanks!
is it possible to workaround such scope behavior?
No. Scopes are inaccessible from outside, and they are necessarily lost on serialisation of a function. You can only stringify "pure" functions like body that do not reference any free variables.
That's also the reason why the JSON format does not include functions.
The main idea is to somehow inject module number one as variable inside second module saving the original scope of methods that are returned.
Inject the reference, not a string. Dependency injection is no magic, all kinds of module loaders for JavaScript do it.

How to force Google Closure Compiler to rename methods even when using objects

It seems that the google closure compiler (http://closure-compiler.appspot.com/home) preserves all of the method names when I use 'this.' or when using a revealing module pattern. It only seems to rename methods to letters when they are not in an object that might be referenced by other external methods. I've tried wrapping both my (Utility) object and the anonymous method that uses it, but this doesn't seem to help. How do you create objects (and separate script files) that might be shared with each other and still have it abbreviate all the method names?
I'm read several posts on SO and do not see anything addressing this, only posts about stuff not getting renamed due to conflicts with external variables.
var Utility = (function () {
this.isDefined = function (v) {
/// <summary>Checks to see if a variable is defined.</summary>
return typeof v !== 'undefined';
}
this.isObj = function (v) {
/// <summary>Checks to see if a variable is an object.</summary>
return typeof v === 'object';
}
...
})();
Then I want to be able to do:
(function(u) {
u.isDefined();
})(Utility);
I've also tried:
var Utility = (function () {
var utility = {};
utility.isDefined = function (v) {
/// <summary>Checks to see if a variable is defined.</summary>
return typeof v !== 'undefined';
}
utility.isObj = function (v) {
/// <summary>Checks to see if a variable is an object.</summary>
return typeof v === 'object';
}
return utility;
...
The revealing object pattern does not work well with closure compiler. Nor does the extra closure you are using which aliases the window and document global variables. The final use case itself is problematic with Closure-compiler as well. Currently, the compiler doesn't handle aliases well especially when passing namespaces as function arguments.
// ==ClosureCompiler==
// #compilation_level ADVANCED_OPTIMIZATIONS
// ==/ClosureCompiler==
var Utility = {};
Utility.isDefined = function (v) {
/// <summary>Checks to see if a variable is defined.</summary>
return typeof v !== 'undefined';
};
Utility.isObj = function (v) {
/// <summary>Checks to see if a variable is an object.</summary>
return typeof v === 'object';
};
(function() {
function myPrivateFunction(x) {
}
Utility.SomeMethod = function(x) {
return myPrivateFunction(x);
};
})();
Utility.isDefined(x);
window['Utility'] = Utility;
Compilation and renaming of this example can be tested at http://closure-compiler.appspot.com/
You can protect your local variables from bleeding into the global scope by using the output_wrapper flag and properly exporting your symbols.
The compiler also specifically disallows usage of the this keyword in non-constructor, non-prototype functions. You should always use the full namespace. The compiler can then flatten the namespace methods (which is why the restriction occurs).
See Which Compilation Level is Right for Me?

Categories

Resources