5
var name = "Bob";

var book = {
    name: "Harry Potter",
    writeName: function() {
        return function() {
            document.writeln(this.book.name);
        }
    }
};

When I call this

book.writeName()();

I want it to print Harry Potter (not Bob) which it does above, however this:

var book2 = book;
book = null;
book2.writeName()();

Now looks for this.book (which is null) where it should be looking for this.book2

How can I reference the variable?

Saro Taşciyan
  • 5,210
  • 5
  • 31
  • 50
  • 6
    Don't use `this`. – Bergi Feb 17 '14 at 13:22
  • @Bergi But when I change to book2 it still looks for book –  Feb 17 '14 at 13:24
  • OK sorry I have to refine: Don't use `this` where inappropriate, like here inside the returned function where [`this`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) refers to the global object :-) – Bergi Feb 17 '14 at 13:32

4 Answers4

5

What you need here is a variable in the writeName closure:

var book = {
    name: "Harry Potter",
    writeName: function() {
        var name = this.name; // turn dynamic property into closure variable
        return function() {
            document.writeln(name);
        }
    }
};
book.writeName()(); // Harry Potter

Instead of storing only the name in the closure, you also could store a reference to the object like in @Quentin's answer. It might make a difference if you plan to change the .name property before calling the returned function.

For the question whether to use this or book for referencing your object see Javascript: Object Literal reference in own key's function instead of 'this'.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
3

Since you are returning a function, you are going to lose whatever context you got from calling the function that generates it.

You need that context to reference the object, so you need to preserve it.

writeName: function() {
    var myBook = this;

You then need to use that preserved context:

    return function() {
        document.writeln(myBook.name);
    }
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
2

try this : http://jsbin.com/pagumiwi/4/edit

var name = "Bob";

var book = {
    name: "Harry Potter",
    writeName: function() {
        return function() {
            document.writeln(this.name);
        }
      }()
    };



book.writeName(); //would also work
var book2 = book;
book = null;
book2.writeName(); //would also work
Royi Namir
  • 144,742
  • 138
  • 468
  • 792
1

Because this changes when the context changes you need to save a reference to the original this. Here I've used _this

var book = {
  name: "Harry Potter",
  writeName: function() {
    var _this = this;
    return function() {
      console.log(_this.name);
    }
  }
};

book.writeName()() //  Harry Potter

var book2 = book;
book = null;
book2.writeName()();  //  Harry Potter

Demo

Andy
  • 61,948
  • 13
  • 68
  • 95