0

I'm starting Addy Osmani's amazing book on javascript design patterns but can't seem to get off the ground. Can anyone tell me what's wrong here with my approach (I'm using Raphael, just for fun.):

var myPaper = Raphael('container', '800', '600');

var myScene = function() {
  var c1 = myPaper.circle(50, 50, 40);
  var c2 = myPaper.circle(50, 150, 40);
  var c3 = myPaper.circle(50, 250, 40);

  c2.attr("fill", "red");  // yep!

  return {
      firstCircle: c1
  };
}

// at some point later i want to call the function...
myScene();

//  ...then even later I want to refer to one of the circles
//  but without creating another global variable.

myScene.firstCircle.attr("fill", "red");  // nope!
console.log(myScene.firstCircle); //  undefined!

http://jsfiddle.net/aGCv8/

2
  • 1
    You don't have the var circ1 defined anywhere, just c1. Commented Jan 29, 2013 at 3:04
  • @dominic right, that's a typo. not the problem though... I fixed it. Commented Jan 29, 2013 at 18:21

1 Answer 1

3

"What's wrong with your approach" is that this isn't the module pattern, revealing or otherwise. If you meant to use it, use it, and make that function self-invoking:

var myScene = function() {
  var c1 = myPaper.circle(50, 50, 40);
  var c2 = myPaper.circle(50, 150, 40);
  var c3 = myPaper.circle(50, 250, 40);

  c2.attr("fill", "red");  // yep!

  return {
      firstCircle: c1         // ← refer to a variable which is actually defined
  };
}();                          // ← parens go here

You don't later call myScene as a function, because it isn't a function, and that anonymous function has already been called. And look, you still get access to that circle!

console.log(myScene.firstCircle); // z {0: circle.[object SVGAnimatedString], node: circle.[object SVGAnimatedString], id: 0, matrix: cb, realPath: null, paper: j…}

Omitting the parentheses (which call the anonymous function) leads to a very different outcome, as you have found.

http://jsfiddle.net/mattball/qR4Fj/

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks a lot Matt. The thing is, I actually do want to be able to call the function later, with a public pointer. When i refactor your code to do that, I'm getting a similar problem: jsfiddle.net/wUbG2
Why do you want to be able to call it later? A module is not supposed to be a function; it is a self-contained logical unit of related functionality. If you want it to be reusable and applied to different locations on a page, don't create/use a module. Create and use a class.
Well, it's called later depending on a bunch of conditional factors. (I'm simplifying greatly for the sake of the example.) It doesn't need to be reusable, or called multiple times. Not to wander off topic here, but also: my understanding of javascript is that there are no classes. I'm really just trying to figure out why myScene.secondCircle returns undefined in that second fiddle...
myScene.secondCircle is undefined because c2 is undefined when the object defining renderCircles and secondCircles is returned. And there are definitely classes! developer.mozilla.org/en-US/docs/JavaScript/…
Oh, man, I knew you were going to go there. I totally appreciate the help, but an academic debate over the nature of "classes" in computer science doesn't really help me right now :) FWIW as I'm sure you know there is a debate on terminology here: stackoverflow.com/questions/2752868/… If renderCircles() has run already, doesn't that define c2?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.