1

I have read this answer and IIFE but I can't seem to find the correct solution to my problem.

I have a simple class here:

define(['jquery'], function($) { // Need 'self' because someCallback() is being called with .call() and 'this' changes var self; function Foo(number) { self = this; this.someNumber = number; } Foo.prototype = { someCallback: function () { //Use self because 'this' changes to a DOM element var num = self.someNumber; //Do something with the num return num * 2; } }; return Foo; }); 

and someCallBack() is being called by a jQuery plugin using .call(). Because of this, the context changed, hence the use of the self variable.

However, this is wrong because:

define(['foo'], function(Foo) { describe('context question', function () { var foo1 = new Foo(1); var foo2 = new Foo(2); it('"this" should work', function () { var call1 = foo1.someCallback.call(this); // 4 var call2 = foo2.someCallback.call(this); // 4 expect(call2).toBe(4); // Only works because it is 'new' last expect(call1).toBe(2); // Fails because 'self' is taken from foo2 }); }); }); 

How exactly should I wrap the self variable to make this code work?

2 Answers 2

1

You could probably just use the revealing module pattern and declare it as a "global" variable (local to the module):

define(['jquery'], function($) { var someNumber; function Foo(number) { someNumber = number; } Foo.prototype = { someCallback: function () { return someNumber * 2; } }; return Foo; }); 
Sign up to request clarification or add additional context in comments.

1 Comment

I tried the code but it doesn't work. The problem is that someNumber will change after I call new Foo(2).
1

Two ways of calling an object method which stores its own this value include

  1. Define the method as a nested function which references its this value in a closure which stores this value in a variable. The function defined could be anonymous or declared with a name but must be evaluated each time a class instance is created, so as to create a new Function object capturing different values of self in function scope.

  2. Take a statically defined function object and bind its this value using bind. Bind creates a new wrapper function object each time it is called.

The first method looks like (without Jquery or Jasmine):

function Foo(number) { var self = this; this.num = number; this.someCallback = function() // method with new Foo object stored as self in function scope { // something with num: return self.num * 2; } } 

and the second method could look like

function Foo(number) { this.num = number this.someCallback = this.someCallback.bind(this); // bind prototypical method as local method. } Foo.prototype = { someCallback: function () { // this value is bound by constructor; //Do something with the num return this.num * 2; } }; 

2 Comments

Thanks. I tried the 2nd method, but it doesn't work. I think the .call() is changing this. The 1st method works great. However, is that a "proper" thing to do? From what I know, this will recreate someCallback() over and over again for each Foo. Is this common? (sorry, still kind of new with creating objects in JS)
If copied and pasted the second method would have failed due to upper casing of "Back" in "someCallback" whereas it should have been lower case. I've updated the second code example - can you confirm if it still fails please? Even so it is quite common to create new function objects in an object constructor, although possibly sometimes due to programming style rather than necessity ;-)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.