Hi Chris, There are a couple of reasons that calling functionB from functionAA didn't work, primarily that you called functionAA without setting its context (its `this` value). So within functionAA, `this` wasn't a reference to the instance. To set its `this` value, we'd either have to make it a property of the instance and then call it via "dotted" notation, or use Function#call (or Function#apply):
functionAA.call(this); But there are larger issues with that code as well. You're using Class.create in a way that defeats the purpose of using it (by replacing the prototype it creates for it with a completely different one). Here's a recast version of that code with minimal changes: * * * * // Definition var Foo = Class.create({ initialize: function(params) { alert('you just created an object, good work.'); }, functionA: function() { functionAA.call(this); function functionAA() { this.functionB(); } }, functionB: function() { alert('function b'); } }); * * * * Note that rather than replacing the prototype afterward, we're passing Class.create an object with properties for each of the methods for the class. That's how Class.create is designed to be used. Regarding that functionA -> functionAA -> functionB thing, the above uses Function#call and that's fine, but for completeness there are at least two other ways that we can do that: A) Passing the instance as a parameter * * * * functionA: function() { functionAA(this); function functionAA(instance) { instance.functionB(); } }, * * * * B) Setting a variable to refer to the instance and then using that variable within functionAA, since functionAA closes over the variable (has access to it): * * * * functionA: function() { var self = this; functionAA(); function functionAA() { self.functionB(); } }, * * * * Which one you use is largely down to personal preference and to what it is you're trying to achieve with defining functionAA within functionA, their performance is virtually identical (the version using the `self` variable is very, very, very slightly faster on all browsers, but you'd have to be doing literally hundreds of thousands of calls for it to matter). So, there we are, that recast code will work (unless I've let a typo slip in), and you'll see that sort of thing done all over the place. In terms of your actual question, that's the end of the answer. ...but you clearly have an interest in this stuff, so I'm going to go a bit off-topic and say that although the code above is fine, it does have a problem in that all of the functions are anonymous. Although the functions are bound to properties, and the properties have names, the functions *themselves* do not. This is an issue when tools try to tell you where you are or where something happened -- the browser telling you where an error occurred, or a debugger telling you what the call stack looks like. Lately my preference has been to use *named* functions wrapped in a scoping function (otherwise their names would leak out into the global namespace, and That Would Be Bad). If we did that, it would look like this: * * * * var Foo = Class.create((function(){ function initialize(params) { alert('you just created an object, good work.'); } function functionA() { functionAA.call(this); function functionAA() { this.functionB(); } } function functionB() { alert('function b'); } return { initialize: initialize functionA: functionA functionB: functionB }; })()); * * * * Note how instead of creating an object literal where the functions are directly assigned to properties, we use an anonymous scoping function, declare our functions within it in the normal way, and then have that scoping function return an object that maps properties to the named functions (the "initialize" property refers to the "initialize" function, etc.). We then execute the anonymous function immediately, and pass the object it gives us into Class.create. Now if we're using a debugger and we're walking through (say) functionB, the debugger can tell us that we're in "functionB" and that the stack looks like this: (?) functionA functionAA functionB (where that (?) is the anonymous function called by the 'load' event.) Whereas with the earlier version using mostly anonymous functions, the call stack would look like this: (?) (?) functionAA (?) ...because the only function with an actual name in the entire stack is functionAA. A second advantage of this scoping function is that you can now easily and cheaply have private methods -- just leave them out of the object you return at the end: * * * * var Foo = Class.create((function(){ function initialize(params) { alert('you just created an object, good work.'); } function functionA() { functionAA.call(this); function functionAA() { this.functionB(); } } function functionB() { alert('function b'); trulyPrivate(); } function trulyPrivate() { alert("I'm truly private"); } return { initialize: initialize functionA: functionA functionB: functionB }; })()); * * * * Nothing but the functions in your class can see the `trulyPrivate` function. The way I called it in the above makes it a class method (rather than an instance method -- `this` has no special meaning within it), but there are ways to use it as an instance method if you like (Function#call, for instance). kangax (you'll see him in this group) has a good article on named function expressions[1] and some gotchas around browser implementations of them (the code above is fine for all browsers, but it's good to know where the gremlins are -- you couldn't safely give your scoping function a name on all browsers, for instance, unless you completely split it out from the line calling Class.create). And if you're interested in more about truly private methods, I wrote up something about those recently[2]. [1] http://yura.thinkweb2.com/named-function-expressions/ [2] http://blog.niftysnippets.org/2009/09/private-methods-in-javascript.html HTH, -- T.J. Crowder tj / crowder software / com www.crowdersoftware.com On Sep 22, 7:33 pm, Chris P <haroldthehun...@gmail.com> wrote: > Hello, > > I'm trying to create a JS class and I'm having some trouble with the > function scope. I have a function within one of the class methods > that is trying to call another class method, but I'm not sure the > right way to call it. Here is an example: > > var Foo = Class.create(); > Foo.prototype = { > initialize: function(params) { > alert('you just created an object, > good work.'); > }, > functionA: function (){ > functionAA(); > function functionAA(){ > this.functionB(); > //this.functionB.bind(this);- > also didn't work > } > }, > functionB: function (){ > alert('function b'); > } > } > > Event.observe(window, 'load', function() { > var bar = new Foo(); > bar.functionA(); > }); > > Any help would be appreciated! > > Thanks, > --Chris --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Prototype & script.aculo.us" group. To post to this group, send email to prototype-scriptaculous@googlegroups.com To unsubscribe from this group, send email to prototype-scriptaculous+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~----------~----~----~----~------~----~------~--~---