3

When I have an Object like this in Javascript:

var Foo = {

   bar: function(location, callback){

     var ref = new Firebase(location);   
     alert(location); // outputs correct, different value when called twice with different locations

     ref.on('value', function(remote) {
         callback(remote, location);
         alert(location); // outputs last value that was given to Foo.bar, set synchronously, 
                          // but when asynchronously getting the value, only last given to Foo.bar() is retrieved
     }.bind(this)) // bind to .bar scope

   }
}

And then do:

Foo.bar("some/location", function(remote, location){
   alert(remote) // "some/location"
});

This would get back some remote object, and the original, requested location (which reference I use locally, so when, in whatever order the calls come back, I can put them in the right place in the local client)

Now, when I try multiple Foo.bar like this:

Foo.bar("some/location", function(remote, location){
   alert(location) // after callback has responded:  "other/location"
});
// some ms have passed, no response/callback from server yet...
Foo.bar("other/location", function(remote, location){
   alert(location) // after callback has responded:  "other/location"
});

The location variable seems to override the first Foo.bar(), which is strange, because as far as I know that variable is in the private scope of Foo and should not be touched?

Not even when I do:

 var Fuu = Object.create(Foo);

Which, as far as I know, would at least create a completely new Object, only inheriting the last set variables, but from its inception on out, should be in its own scope. Or am I misunderstanding some fundamental thing here? Or is it the asynchronous Firebase library I'm using?

Is the inheritance different when I would do the following? And how/why?

var Foo = function(){

    this.bar = function(){

    }

}

To clarify: After either async calls callback, the last location variable given to Foo.bar() seems to overwrite the first within the Firebase scope, and I get the right remote object, but not the right, associated location, which reflects where the remote object should go in my client code, locally.

Update* I changed Async() to Firebase() in my question, which I'm actually using, but I don't think it is its fault, because I'm just passing along a variable, and binding it to this to keep te reference, but it looks like, because Foo.bar is the same function(object?), it overwrites the first given location variable to the last one that Foo.bar received..

Update Added .bind(this) to the question, to pass the variable to the async function and made the callback function that output wrongly

TrySpace
  • 2,233
  • 8
  • 35
  • 62
  • Your `Foo` seems to be fine, maybe there is something wrong with `Async`. – Bergi Jul 15 '14 at 21:25
  • @Bergi [I'm not so sure](http://jsfiddle.net/8Lu5c/)... – DontVoteMeDown Jul 15 '14 at 21:26
  • I updated my question, and added the `location` variable to the callback, which is rather essential to my question – TrySpace Jul 15 '14 at 21:36
  • I didn't mean the `Object.create` call (which is not the solution anyway, as the properties of `Foo` are irrelevant to scope). I meant your `bar` function, which *on every invocation* creates its own set of `location`, `callback` and `ref` variables. – Bergi Jul 15 '14 at 21:50
  • This might be a "feature" of Firebase though, which I'm not familiar with. – Bergi Jul 15 '14 at 21:51
  • 1
    What exactly is `Async`? I couldn't find it in the Firebase docs – Bergi Jul 15 '14 at 22:05
  • 2
    Async isn't anything in the Firebase docs. Could you share what you're doing with the Async code? I imagine you're just creating a Firebase reference from a root location. – David East Jul 15 '14 at 22:30
  • @Bergi, as far as I know, you should be able to listen to multiple locations, or even multiple listeners on the same location (which is why you have to make sure to turn them `.off()` when needed. And still, it is a seperate value, that belongs to each instance of `Foo.bar()`.. – TrySpace Jul 15 '14 at 22:49
  • How do you know that it's the second callback that fires (where the `location` has an unexpected value), and not the first callback that just fires twice? – Bergi Jul 15 '14 at 23:15
  • @Bergi, when I don't call it the second time, the correct `location` is returned/alerted, and only once – TrySpace Jul 15 '14 at 23:17
  • try console.log in place of alert – Kato Jul 19 '14 at 15:29
  • 1
    Shouldn't ref.toString have the location? – Zack Argyle Jul 21 '14 at 03:22
  • Either way you probably want a new Foo.bar() and then use this to store the location – Zack Argyle Jul 21 '14 at 03:30

1 Answers1

0

this might answer my question:

https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&%20object%20prototypes/ch1.md

this is actually a binding that is made when a function is invoked, and what it references is determined entirely by the call-site where the function is called.

This seems to explain my misunderstanding of the this binding as well:

function foo() {
    console.log( this.a );
}

var obj = {
    a: 2,
    foo: foo
};

var bar = obj.foo; // function reference/alias!

var a = "oops, global"; // `a` also property on global object

bar(); // "oops, global"

Can anyone confirm that my .bind(this) might be the explanation for this unexpected behaviour, and the article is correct?

TrySpace
  • 2,233
  • 8
  • 35
  • 62
  • The article is correct (as far as I can tell from skimming over it), but your attempt of `.bind()`ing is futile. You did not use `this` in your code, so you don't have any problems with it. You might want to read the [scope chapter](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&%20object%20prototypes/ch1.md#its-scope) again: *To be clear, `this` does **not**, in any way, refer to a function's **lexical scope***. "Unless that scope is the global scope", the article seems to have forgotten to add (which is just source of more confusion) – Bergi Jul 22 '14 at 12:45
  • While `.bind(this)` might not do exactly what I thought it did, futile it is not, because without it, the `location` variable would not be readable within the Firebase ref callback function. – TrySpace Jul 22 '14 at 15:55
  • No! `location` *is* available in the *scope* [because of **closure**](http://stackoverflow.com/q/111102/1048572). You don't need to do anything explicitly to make it available. Least bind the [`this` context](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) that is not referred to in any way. – Bergi Jul 22 '14 at 17:19