JavaScript Closure problem again! - javascript

This is what i am facing with
function AAA(){
this.f1 = function (){
/*expecting that f2 will be call as both of then are of same object.*/
console.log(f2(5));//
}
this.f2 = function(x){
return x;
}
}
x = new AAA();
x.f1(); //ReferenceError: f2 is not defined
Neither does it work,
function AAA(){
this.f1 = function (){
/*expecting that f2 will be call as both of then are of same object.*/
console.log(f3(5));//
}
/*naming the function f3 hope to get function reference, as function
on the right side has name now and in the closure of f1, right?*/
this.f2 = function f3(x){
return x;
}
function f4() {};
}
x = new AAA();
x.f1(); //ReferenceError: f3 is not defined
What is happening here? who are in closure of 'f1' except 'f4'? can't we call the same object function without 'this'?

You are not really using closures here. It will work fine if you change the line to
console.log(this.f2(5));
If you want to use closures, you can rewrite the class as follows:
function AAA()
{
var f1 = function()
{
console.log(f2(5));
};
// f2 is a private function.
var f2 = function(x)
{
return x;
};
// Define the public interface.
return { f1: f1 };
}

You’re confusing a few things here; this and closures are two completely different issues.
Your problem here is that you’re trying to refer to f2 directly, thereby assuming that this is part of the current execution scope. It isn't.
If you put f2 on this, you’ll have to keep referencing it as this.f2. To be able to reference f2 directly, you’ll have to declare a (separate) variable by that name, which you can then assign to this if you want, as qwertymk says.
Personally, I try to avoid this as much as I can, since its meaning is completely dependent on how the function is called (e.g. if AAA is called without specifying the new operator, this will refer to the global object!). It also saves you from headaches like the one above. Closures (as demonstrated by Elian) are a much better way of obtaining this functionality.
Interestingly enough, I've found I hardly ever need to use this.
In Elian's example, f2 is closed over: once the AAA function is done running, nobody can access f2, except the functions that were defined inside AAA (and are still accessible). In this case, the function f1 is accessible from the returned object, so that still exists. Therefore, f1 can still use f2.
That's what closures are about: a function can still access all the variables in its scope, even when those variables were declared in a function that's terminated.

It should be this.f2() not f2() by itself. You would use f2() if it was a private variable which means if it was created with a var keyword.
function AAA(){
var f3 = function(x) { return x; };
this.f1 = function (){
/*expecting that f2 will be call as both of then are of same object.*/
console.log(this.f2(5));//
console.log(f3(10));
}
this.f2 = function(x){
return x;
}
}
DEMO

Others have already told you what the problem is, so i will not repeat it. If you want your code to work, you just need a reference to this:
function AAA(){
var self = this;
this.f1 = function (){
console.log(self.f2(5)); //self.f2 exists, yay
}
this.f2 = function(x){
return x;
}
}
x = new AAA();
x.f1(); //5

Related

Local variable inside a method, and assigning a function?

I came across some codes that for me it looked confusing, although I looked in many places googling, I could not find the exact answer for my question. In hope to know what's going on with this code I'm here, asking if there's a good explanation for me, so I would not only know how to do it but, learn what it does as well!
var fun = {
a_method: function(){
var f = function(){
alert("FUN FUNNY FUNCTION");
};
f.another_method = function(){ // in this line, is another_method local or not? Because like mentioned f is local; how about another_method after the dot?
alert("this is another method inside my fun method");
};
return f; // this is a local variable, why another_method isn't local?
}() // these parentheses, what do they do in regards to the function?
};
What does return f do? Why does f.another_method(){function(){}} become fun.a_method.another_method() <= these parentheses confuse me because if f is local inside a_method, likewise shouldn't everything else be local as well? Like f.another_method(){function(){...}}, or to even be clearer I want to know why the .another_method() with an f preceding the function(before the dot) return f. and goes passed to another_method()? To be called fun.a_method.another_method(); and no f in there see where the confusion is.
fun.a_method.another_method() <= these parentheses confuse me
f.another_method(){function(){}};
I should call it this way, but I'm not right (why, just because the variable is local) and this is not how it works with JS:
fun.a_method.f.another_method();
Trying to understand why not the above instead:
fun.a_method.another_method(); // note that it is without the "f" when it's called, now why not or "how it became this way"?
var anonymous = function(){var f = function(){alert()}; return f}();anonymous();
var anonimo = {method:function(){var f = function(){alert("this is an anonimous function")}; return f;}()}
anonimo.method();
var why = {method:function(){
var f = function(){
alert("this an anonymous function because the function was declared from a variable, is this right?")
};
f.notHere = function(){
alert("correct me if I'm wrong but, f is variable declared to an anonymous function just f alone \"notHere\"")
};
return f
}()};
why.method.notHere();
var lastScenario = {
method:function(){
var f = function(){};
f.notHere=function(){
alert("this will not work if I don't declare f as a function")
};return f}()};
lastScenario.method.notHere();

Newly created objects call to constructor undefined if constructor is inside another function

I just learned OOP and there is one little thing that I am not able to solve. The problem is a scope issue of some sort.
If I create a new object then how will I be able to give it access to my constructor function if the constructor function is inside another function? Right now I get undefined. Storing the function in a global variable wont do the job.
var example = new something x(parameter);
example.i();
var getFunction;
var onResize = function() {
getFunction = function something(parameter) {
this.i= (function parameter() {
// Does something
});
};
};
window.addEventListener('resize', onResize);
onResize();
For OOP javascript, the pattern should be like this.
//defining your 'class', class in quotes since everything is just functions, objects, primitives, and the special null values in JS
var Foo = function (options) {
// code in here will be ran when you call 'new', think of this as the constructor.
//private function
var doSomething = function () {
}
//public function
this.doSomethingElse = function () {
}
};
//actual instantiation of your object, the 'new' keyword runs the function and essentially returns 'this' within the function at the end
var foo = new Foo(
{
//options here
}
)
If I understand you, you want to know how to access variables inside another function. Your attempt is reasonable, but note that getFunction is not bound until after onResize is called. Here's a bit of a cleaner demo:
var x;
function y() {
// The value is not bound until y is called.
x = function(z) {
console.log(z);
}
}
y();
x('hello');
A common JavaScript pattern is to return an object that represents the API of a function. For example:
function Y() {
var x = function(z) {
console.log(z);
}
return {
x: x
};
}
var y = Y();
y.x('hello');
You should definitely read up on the basic concepts of JavaScript. Your code and terminology are both sloppy. I'd recommend Secrets of the JavaScript Ninja. It does a good job explaining scope and functions, two tricky topics in JavaScript.

Is it possible to change scope of function after new Function()?

So I have this code:
function fn(a){
var f=(new Function("return a"));
return f();
}
fn(7)//ReferenceError: a is not defined
Same problems with local variables:
function fn(){
var a=7;
var f=new Function("return a");
return f();
}
fn(7)//ReferenceError: a is not defined
I want it to return a but the new function cant see a,
it can only see global a
var a=1;
function fn(a){
var f=(new Function("return a"));
return f();
}
fn(7)//1
With the normal initialization the function can see the argument.
function fn(a){
var f=function(){return a};
return f();
}
fn(7)//7
I need to call the basic constructor in my project and can't use global variables.
I know that i could solve this by giving arguments to the newly created function and call it with that like this:
function fn(a){
var f=(new Function('a',"return a"));
return f(a);
}
fn(7)//7
And also could use some parsing function and some stupidly long method to make incoming arguments reachable like this:
function parsargs(funct){
//some parsing methodes giving back argument name list from funct.toString()
return "['a','b']";//like this
}
function fn(a,b){
var arrgstr,retfunc;
arrgstr="";
for(var i in arguments)
{
if(i<arguments.length-1)
arrgstr+=arguments[i]+",";
else
arrgstr+=arguments[i];
}
//return arrgstr;
retfunc="var f=new Function("+parsargs()+",'return b*a');return f("+arrgstr+")";
return (new Function(retfunc))();
}
fn(7,4)//28
But there must be an easier way which reaches local variables and functions as well...
Any suggestions?
PS:
i am trying to replace eval() in the project
Here is a simplified version of my original problem:
fiddle
The answer is NO...
Your exact question isn't clear but, supposing you can use arguments.callee (i.e. non strict mode) and that you want to be able to have any arguments name in fn, you "may" do this:
function fn(a,b){
var strargs = arguments.callee.toString().match(/\(([^\)]*)\)/)[1];
return (new Function(strargs.split(","),"return a+b")).apply(null,arguments);
}
console.log(fn(7, 3)) // 10
But I have a strong feeling this is a XY question and that we could have given a more useful answer knowing the real original problem to solve.
You could call your new Function with a context that references the local variables that you need:
function f(a) {
var b = 30;
return new Function("return this.a + this.b").call({ a: a, b: b })
}
f(10) // 40
The reason why this isn't working as easy as you would like is that JavaScript doesn't blindly put variables in a scope. Instead, it parses the function body (as good as it can) and determines which variables the code will need. It will then look up the variables in the outer scopes, create references for them and attach those references to the new function. That's what keeps variables from the outer scope accessible inside of the function when it eventually will be executed.
You want to build a function from a string body. JavaScript can't tell which variables the body will use and hence, it won't make those variables available.
To make it work for function arguments, use apply()::
function fn(a){
var argref = arguments; // create reference to the arguments of fn() and hence to a or any other arguments
var func = new Function("return arguments[0]");
var wrapper = function() {
return func.apply(null, argref);
};
return wrapper;
}
Note that you still can't reference arguments by name since the code never specifies what the names of the arguments of func are - JavaScript can't magically read you mind and do what you want. If you want to access the arguments by name, you need to tell the interpreter the names.
This question has some code how to determine the names from a function reference: How to get function parameter names/values dynamically from javascript
I don't see a way to make local variables available without passing them to fn() as arguments. Even if you used them inside of fn(), they would be out of scope when func() is eventually executed.
A simple solution would be to pass an object to fn():
function fn(conf) {
var func = new Function('conf', "return conf.a");
var wrapper = function(conf) {
return func.apply(null, conf);
};
return wrapper;
}
fn({a:7});
new Function doesn't create a closure context, but eval does.
Here's a low-tech way to build a function with an arbitrary evaluated body and access to the calling scope:
function f(a) {
return eval("(function() { return a })")()
}
f(10) // 10

Adding a function to global windows object

I was playing around with javascript objects to understand "this" and function context better. I stumbled across this problem. I get the error "obj2 is not defined" unless I run window.obj2() after assigning it, but I don't know why. Shouldn't it be enough to assign the function to window.obj2 without also executing it immediately afterwards? I know that you're not supposed to pollute the window object, this is just a test.
Thanks!
window.obj2 = function(){
console.log('obj2 in window.object',this);
}
window.obj2(); // problem when this line is commented out
(function () {
var parent = {
obj : function(){
//console.log(this);
obj2();
this.obj2();
window.obj2();
},
obj2 :function(){
console.log('obj2 in parent',this);
}
}
parent.obj();
}());
EXPLANATION
OP asks why does he have to execute the function after defining it in order for it to become defined later in the code... See what happens when you comment out the problem line.
Solution to the mystery:
You forgot a semicolon:
window.obj2 = function(){
console.log('obj2 in window.object',this);
}; // <--
Without it, the code will be interpreted as
// I'm naming the functions to refer to them later
window.obj2 = function a(){
...
}(function b() { ... }());
I.e. the parenthesis around b are interpreted as call operation of a (just like you did with b itself: (function b() {...}()).
The engine first executes b in order to pass the return value as argument to a, and only after that the return value is assigned to window.obj2.
So, at the moment b is called, window.obj2 does indeed not exist yet.
So, the reason why adding window.obj2() makes it work is not because you are accessing window.obj2, but because it makes the code un-ambigious. The following parenthesis cannot be interpreted as call operation anymore. You could use any statement there, e.g.
window.obj2 = function(){
console.log('obj2 in window.object',this);
}
"foo";
(function () {
obj2();
}());
If you defined function window.obj2 inside the anonymous function which does call itself then it works fine, have a look code.
<script>
//window.obj2(); // problem
(function (window) {
window.obj2 = function(){
console.log('obj2 in window.object',this);
}
var parent = {
obj : function(){
//console.log(this);
obj2();
this.obj2();
window.obj2();
},
obj2 :function(){
console.log('obj2 in parent',this);
}
}
parent.obj();
}(window));
</script>
<body>
</body>

Does the var becomes a function because of a javascript function stored in a var?

In below example about Scope, I dont understand that how could a variable is running as a function? in here var f is running as f(). However, is this a sound method to run f in JavaScript? Why? Is it because var f stored a function?
var myFunction = function() {
var foo = "hello";
var myFn = function() {
console.log( foo );
};
foo = "ddd";
return myFn;
};
var f = myFunction();
f(); // "ddd"
Thanks!
This line of code will run the function myFunction and assign its return value to f.
var f = myFunction();
myFunction returns a reference to the function myFn. As a result, f is now a reference to myFn and when you attempt to call f using f() it calls myFn because that is where the reference points.
jsFiddle Demo
There is a similar approach which returns an object with functions
var init = function(){
return {
hello: function(){ console.log("hello"); },
world: function(){ console.log("world"); }
};
};
Which could then be used like this:
var f = init();
f.hello();
f.world();
In scripting languages in general and functional programming. You can use functions as you would a variable. For example: in both paradigms typically(not aware of any languages that don't) functions can be passed as parameters, etc...
Functions are objects in javascript, so they can be assigned to variables and passed around like any other value. And eventually they can be executed.
What's happening here is that myFunction returns a function, which can then of course be executed.
Let me simplify your example:
// function that returns a function.
var foo = function() {
// declare a function, but don't run it right now.
var fn = function() {
return "bar";
};
// return the function object.
return fn;
}
var someFn = foo(); // function object is returned from foo()
someFn(); // "bar" is returned
// Which means you could also do this!
// the first () executes foo, second () executes the function returned by foo()
foo()() // "bar" is returned
In this example, foo() returns a function. This function is saved to the local variable someFn and then executed.
Functions that return functions are a little tricky to wrap you head around sometimes, but it's one of the most powerful features of javascript as it allows you do some very tricky things.

Categories