Object function scope - javascript

factory(n) returns objects with functions.
func1 function definition creates its own scope, and x inside this function references x = n + ''.
But func2 is a reference and the scope is wrong.
Is there a way to return an object from create so its functions were references (not separate definitions)?
Actually, I'm fine with func1 approach while function definition footprint is small. If it is a complex function it would be better not to clone this function into every object comming from factory(n). inner_func may not use this, it is simple function. Also I want to avoid new and this.
var factory = (function(){
var x = '!';
return function create(n){
var x = n + '';
return {
func1: function(y){return inner_func(x, y); },
/* vs */
func2: inner_func_api
}
}
function inner_func_api(y){ return inner_func(x, y); }
function inner_func(a, b){ return a + b; }
}());
var f1 = factory(2);
var f2 = factory(3);
var f1_func1 = f1.func1(4);
var f2_func1 = f2.func1(5);
var f1_func2 = f1.func2(4);
var f2_func2 = f2.func2(5);
console.log(f1_func1, f2_func1); //24 35
console.log(f1_func2, f2_func2); //!4 !5

You could define that function separately from the object initializer on the return statement:
var factory = (function(){
var x = '!';
return function create(n){
var x = n + '';
function func1(y) {
return inner_func(x, y);
}
return {
func1: func1,
/* vs */
func2: inner_func_api
}
}
function inner_func_api(y){ return inner_func(x, y); }
function inner_func(a, b){ return a + b; }
}());
However, it makes no practical difference, and it doesn't matter how big or complicated that function is. Function instances do take up space, but the code for the function is constant (immutable) and doesn't need to be part of every Function object created from the same piece of source code.

Related

Closures: Scope Chain Variables - Not sure how variables link up

Really new to Javascript. This code is taken from MDN.
// global scope
var e = 10;
function sum(a){
return function sum2(b){
return function sum3(c){
// outer functions scope
return function sum4(d){
// local scope
return a + b + c + d + e;
}
}
}
}
var s = sum(1);
var s1 = s(2);
var s2 = s1(3);
var s3 = s2(4);
console.log(s3) //log 20
When I try to input different variable names (EX below) they don't seem to work and I don't understand how everything links up together to spit out the answer 20.
// global scope
var e = 10;
function sum(a){
return function sum2(b){
return function sum3(c){
// outer functions scope
return function sum4(d){
// local scope
return a + b + c + d + e;
}
}
}
}
var w = sum(1);
var x = s(2);
var y = s1(3);
var z = s2(4);
console.log(s3) //log 20
When I change it to this it also does not work. The console tells me that sa is not defined
// global scope
var e = 10;
function sm(a){
return function sa(b){
return function sb(c){
// outer functions scope
return function sc(d){
// local scope
return a + b + c + d + e;
}
}
}
}
var s = sm(1);
var s1 = sa(2);
var s2 = sb(3);
var s3 = sc(4);
console.log(sc) //log 20
I can keep throwing out more examples that don't work. Someone, please help me understand how the first example works.
function sm(a){
return function sa(b){
return function sb(c){
// outer functions scope
return function sc(d){
// local scope
return a + b + c + d + e;
}
}
}
}
The function sm is taking one argument and is returning a function which takes one argument. The function sm returns is not named sb. Try to think of it as the return value of sm .
So, when you do
var s = sm(1);
The returned function is stored in the variable s
Now if you want to run the second function (sa inside sm) you need to invoke s.
var s1 = s(2);
The returned function (sb) is stored inside varibale s1.
Similarly,
var s2 = s1(3);
var s3 = s2(4);
console.log(s3); // 20

JavaScript Closure - trying to understand following code

Coming from Java background trying to make sense out of the following code.
From:
https://medium.freecodecamp.com/lets-learn-javascript-closures-66feb44f6a44#.cbk6c4e9g
For function bar(c), which line passes argument c into bar(c) as I don't see it here.
Thanks.
var x = 10;
function foo(a) {
var b = 20;
function bar(c) {
var d = 30;
return boop(x + a + b + c + d);
}
function boop(e) {
return e * -1;
}
return bar;
}
var moar = foo(5); // Closure
/*
The function below executes the function bar which was returned
when we executed the function foo in the line above. The function bar
invokes boop, at which point bar gets suspended and boop gets push
onto the top of the call stack (see the screenshot below)
*/
moar(15);
When your first statement of function call var moar = foo(5) is executed
moar variable will be function bar(c){var d=30;return boop(x+a+b+c+d);
check the snippet for understanding
var x = 10;
function foo(a) {
var b = 20;
function bar(c) {
var d = 30;
return boop(x + a + b + c + d);
}
return bar;
}
var moor=foo(10);
console.log(moor);
2.After this statement moar(15),your are actually passing 15 to the bar method
It will execute bar method with c as 15. Now this function would return boop(80) which would just be -80
var x = 10;
function foo(a) {
var b = 20;
function bar(c) {
var d = 30;
return boop(x + a + b + c + d);
}
function boop(e) {
return e * -1;
}
return bar;
}
var moar = foo(5)
console.log(moar(15));
Hope it helps
moar(15) passes 15 into bar which gets copied into parameter c.
The // Closure comment is misleading because it is more useful to think of the closure being configured at the point of declaration of a function.
The reality is that the pointer to the outer lexical environment is configured when a function object is instantiated, and then this pointer is then copied to the execution context associated with any invocations of said function object.

can a function reference itself in javascript?

Suppose we define a function that simply increments its input by some stored value dd:
var obj={}
obj.dd=1
obj.f=function(x){
return x+this.dd
}
Alternatively you could create a closure for dd as follows but this would create a static increment as opposed to one that could be altered later:
var dd=1
var f=function(x){
return x+dd
}
We could alternatively store dd in the function itself:
var obj={}
obj.f=function(x){
return x+this.f.dd
}
obj.f.dd=1
I am curious as to whether it is possible for a function to retrieve a variable attached to itself without going through a parent object, something like a self keyword that would refer to the function itself and would allow the following:
var f=function(x){
return x+self.dd
}
f.dd=1
I know it is unnecessary to do such a thing but I think it would be cool if you could.
You can give function literals a name:
var f = function me(x) {
return x + me.dd;
};
f.dd = 1;
This doesn’t work properly in older versions of IE/JScript, though, as me and f don’t reference the same object. The (deprecated and not usable in strict mode) alternative is arguments.callee:
var f = function(x) {
return x + arguments.callee.dd;
};
f.dd = 1;
Also, your note about the closure isn’t quite right; it can be altered later, even through another function:
var dd = 1;
var f = function(x) {
return x + dd;
};
var setdd = function(_dd) {
dd = _dd;
};
A function is an object. If you reference the var holding the function:
var f = function (x) {
return x + f.dd
};
f.dd = 1;
alert(f(1));
result: 2
If the function is named, you can do the same:
function foo(x) {
return x + foo.dd;
}
foo.dd = 1;
alert(foo(1));
result: 2

Is there a better way to bring all scoped variables of one function into another?

Please consider the following code:
<html>
<head>
<script type="text/javascript">
function a(){
var v = 9;
var w = 2;
var x = 7;
var template = '{w} + {x} = {v}';
var func = eval('(' + c.toString() + ')');
func(template);
}
function b(){
var v = 1;
var y = 'hello';
var z = 'world';
var template = '{v}. {y} {z}';
var func = eval('(' + c.toString() + ')');
func(template);
}
function c(template){
var re = /{(.+?)}/;
var match = template.match(re);
while (match != null){
template = template.replace(re, eval(match[1]));
match = template.match(re);
}
alert(template);
}
</script>
</head>
<body>
<input type="button" value="a" onclick="a()"/><br/>
<input type="button" value="b" onclick="b()"/><br/>
</body>
</html>
This code has two functions (a and b) and a parsing function c that receives a string template as parameter and parses it, using variables that are scoped in the calling function (a or b).
This means that function c has to 'know' all the variables that are known to whichever function was calling it.
What I want is for c to 'know' all the variables in the scope of its caller.
My solution was this line of code in a and b:
var func = eval('(' + c.toString() + ')');
What this does is redefine c as func inside the calling function, so in effect making it a sub function of the caller and thus bringing it into the same scope.
This solution works great, but the problem with it is that it's ugly. I have to turn c into a string and re-eval it to a function every time I want to use it. I'm hoping someone can suggest a better solution, if such exists.
I don't want to pass all the variables as parameters to c because:
The template to parse can be very big and include anywhere from1 to dozens of variables.
If I pass all the variables as parameters to c and access them using the arguments array in c it means I have to use array notation inside the template which is bad practice for obvious reasons.
Putting all the variables into a hash map object and passing that object as parameter to c is possible, but makes for a huge coding overhead to create this hash map from the caller's variables before any call to c.
Note:
Please don't bother pointing out to me that the parsing function is not perfect, it's just a simplified example of my actual code.
You're overcomplicating things. You can eliminate the need to cross scopes by packing your replacement values as an object rather than as individual variables, and using the g flag and a replacement function allow you to greatly simplify c(). Give this a try:
function a(){
var values = {
v: 9,
w: 2,
x: 7
};
func(c('{w} + {x} = {v}', values));
}
function b(){
var values = {
v: 1,
y: 'hello',
z: 'world'
};
func(c('{v}. {y} {z}', values));
}
function c(template, values) {
return template.replace(/{(.*?)}/g, function(match) {
return values[match[1]];
});
}
After playing with it for a while, this is the closest I've been able to come to passing the local scope into another function. It's seriously hacky, involves a fair bit of code duplication, and still needs eval() (though not as much), but it may be what you're looking for.
Basically, this involves declaring all of your local variables as function parameters (instead of using var statements) so that their names can be extracted by converting the function back to source via .toString(). These parameters are not supplied when calling a() and b()!
(Note that the c() function here is identical to the one in my other answer.)
rxArgs = /^[^(]+\(([^)]+)\)/;
function a(v, w, x){
v = 9;
w = 2;
x = 7;
var args = rxArgs.exec(arguments.callee.toString())[1].split(", ");
var i = args.length, values = {};
while (i--) values[args[i]] = eval(args[i]);
func(c('{w} + {x} = {v}', values));
}
function b(v, y, z){
v = 1;
y = 'hello';
z = 'world';
var args = rxArgs.exec(arguments.callee.toString())[1].split(", ");
var i = args.length, values = {};
while (i--) values[args[i]] = eval(args[i]);
func(c('{v}. {y} {z}', values));
}
function c(template, values) {
return template.replace(/{(.*?)}/g, function(match) {
return values[match[1]];
});
}
At this point, however, you're introducing so much boilerplate into each function that you're probably better off simply inlining c() instead.
function a(){
var v = 9;
var w = 2;
var x = 7;
func('{w} + {x} = {v}'.replace(/{(.*?)}/g, function(match) {
return eval(match[1]);
}));
}
function b(){
var v = 1;
var y = 'hello';
var z = 'world';
func('{v}. {y} {z}'.replace(/{(.*?)}/g, function(match) {
return eval(match[1]);
}));
}
I would strongly suggest having your code really parse the templates and interpret the "{foo}" references explicitly in your own code, instead of using eval() for everything.
It's not really clear why code like your "a()" and "b()" examples even need a template mechanism. In a language with first-class function objects like Javascript, what your code seems suspiciously desirous of achieving can be done much better by just programming functionally.
EDIT:
Your question seems to imply that the values will be coming from the caller. If they're all coming that way, you could just pass along the arguments object to c.
Then in the c function, grab the next item in the arguments object you passed for each match in the template.
Example: http://jsfiddle.net/u99Bj/1/
function a(){
var template = '{w} + {x} = {v}';
c(template,arguments);
}
function b(){
var template = '{v}. {y} {z}';
c(template,arguments);
}
function c( template, args ){
var re = /{(.+?)}/;
var i = 0;
var match = template.match(re);
while (match != null){
template = template.replace(re, args[i++]);
match = template.match(re);
}
alert(template);
}
If some of the functions will have some static values, then you would need to convert the arguments into an Array, and supplement the Array as needed.
Can't you do that :
function c(template,caller)
{ ...
}
and call
c(template,this)
then you could just get the variables as members of this (passing the function as an object instead of passing its scope)
EDIT
What about this approach?
function a(){
this.v = 9;
this.w = 2;
this.x = 7;
this.template = '{w} + {x} = {v}';
}
function c(obj){
var template = obj.template;
var re = /{(.+?)}/;
var match = template.match(re);
while (match != null){
template = template.replace(re, obj[match[1]]);
match = template.match(re);
}
alert(template);
}
<input type="button" value="a" onclick="c(new a())"/><br/>
What about this, using simply this keyword
<script type="text/javascript">
function a(){
this.v = 9;
this.w = 2;
this.x = 7;
var template = '{w} + {x} = {v}';
c(template);
}
function b(){
this.v = 1;
this.y = 'hello';
this.z = 'world';
var template = '{v}. {y} {z}';
c(template);
}
function c(template){
var re = /{(.+?)}/;
var match = template.match(re);
while (match != null){
template = template.replace(re, eval(match[1]));
match = template.match(re);
}
alert(template);
}
</script>
All variables will be initialized in document by default. You can encapsulate in other objects. Be careful about optional variables, as they may not be cleared on method call, and may interfere with parsing.

How to have function recall private variable between invocations

Here's an easy one straight from the text book I can't seem to find.
I have a javascript function. I want it to contain a private variable which remembers its value between invocations.
Can someone jog my memory please.
Create it using a closure:
function f() {
var x = 0;
return function() {return x++;};
}
Then use it as follows:
> g = f()
function () {return x++}
> g()
0
> g()
1
> g()
2
var accumulator = (function() {
var accum = 0;
return function(increment) {
return accum += increment;
}
})();
alert(accumulator(10));
alert(accumulatot(15));
Displays 10 then 25.
I am not sure if I understood correctly but maybe something like this would do the trick :
function Foo() {
var x = "some private data";
return {
getPrivateData : function(){
return x;
}
};
};
var xx = new Foo();
xx.getPrivateData();
Here is a truly private implementation
(function() {
var privateVar = 0;
window.getPreviousValue = function(arg) {
var previousVal = privateVar;
privateVar = arg;
return previousVal;
}
})()
alert(getPreviousValue(1));
alert(getPreviousValue(2));
Cheers

Categories