JavaScript Method Context With Circular Invocation In Conjunction With Call() Or Apply()

Posted April 24, 2012 at 10:04 AM by Ben Nadel

Tags: Javascript / DHTML

In JavaScript, you can change part of the execution context using the call() and apply() methods. These allow you to explicitly define the binding of "this" at the time of method invocation. While I use these functions all the time, I realized recently that I was unsure what would happen if you created a circular invocation chain using an overridden method. To ease my mind, I created a small experiment:

  • <!DOCTYPE html>
  • <html>
  • <head>
  • <title>Testing JavaScript Context</title>
  •  
  • <script type="text/javascript">
  •  
  •  
  • // For this test, we are going to look at how circular
  • // method invocations work in the context of a method
  • // that has been invoked with either call() or apply().
  • var testHarness = {
  •  
  • one: function(){
  • console.log( "Real Context!" );
  • },
  •  
  • two: function(){
  • this.one();
  • }
  •  
  • };
  •  
  •  
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  •  
  •  
  • // To test the circular invocation and this-based context,
  • // we need to override the "one" method, and have it invoke
  • // the "two" method so we can then see what version of "one"
  • // it will turn around and invoke.
  • function one(){
  •  
  • console.log( "FAKE Context!" );
  •  
  • // Create circular invocation.
  • this.two();
  •  
  • }
  •  
  •  
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  •  
  •  
  • // Invoke "fake" ONE in the context of the test harness.
  • one.call( testHarness );
  •  
  •  
  • </script>
  • </head>
  • <body>
  • <!-- Left intentionally blank. -->
  • </body>
  • </html>

Here, we have a test object with two methods: one() and two(). In its natural state, two() invokes one() but, one() never invokes two(). Then, we create a completely separate function which overrides the "one" method and invokes two(). Does this create a circular reference problem?

When we run the above code, we get the following console output:

FAKE Context!
Real Context!

When we run the the override method, we clearly get the fake (ie. explicitly changed) context. But, when that function invokes two(), which subsequently invokes one(), the "second" invocation of one() reveals that its context is the original context.

No circular references were created.

When I saw this, I suddenly had clarity - I realized that my previous mental model of call() and apply() was completely wrong. I kept thinking about it as some sort of temporary, runtime method injection magic. I kept thinking about it as overriding part of the target context's object definition. In reality, it's nothing more than an overriding of the given method's "this" binding. There's nothing more to it. There's no relationship between the method being invoked and the context that is being applied.

In retrospect, this should have been completely obvious. I guess at some point, I had just created a false mental model of how things worked and never stopped to question it. Clarity for the win!




Reader Comments

Apr 24, 2012 at 10:21 AM // reply »
8 Comments

Thanks for this clarity.
I have not tested it yet but yeah, it's obvious. Apply and call simply override the context and do not create a "mixin context" who contains both the second one() and the two().

I don't remember if it was detailled in, but I found a very well explanation of the javascript core: http://dmitrysoshnikov.com/ecmascript/javascript-the-core/


Apr 24, 2012 at 10:46 AM // reply »
11,238 Comments

@Loic,

I think part of my distortion came from the fact that my primary programming language - ColdFusion - doesn't have a call() or apply() equivalent. As such, in that language, you actually DO have to fine way to use method injection rather than overriding the "this" binding. So, while I know how call() and apply() work, it was being colored improperly by my understanding of a different language altogether.


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 17, 2013 at 7:42 PM
HashKeyCopier - An AngularJS Utility Class For Merging Cached And Live Data
Ben - thanks so much for posting these Angular articles and findings, they've been a huge help towards learning one of the more 'complex' JavaScript frameworks out there (IMO). I have been using Angu ... read »
May 16, 2013 at 5:01 PM
UPDATE: Parsing CSV Data Files In ColdFusion With csvToArray()
Your code was the closest thing I've found to obtaining some direction for converting ISO fields to values that CF can translate properly. Thank you for posting! ... read »
May 15, 2013 at 10:37 PM
Very Simple Pusher And ColdFusion Powered Chat
hi id making plz easy ... read »
May 15, 2013 at 6:07 PM
Making SOAP Web Service Requests With ColdFusion And CFHTTP
Ben, you once again saved my bacon at work. Thank you, thank you, thank you! ... read »
May 15, 2013 at 4:15 PM
What If All User Interface (UI) Data Came In Reports?
@Josh, Thanks! @Ben, I definitely recommend the David West book "Object Thinking" I've been quoting from. It goes deeply into the philosophy and history of OO programming. His breadth ... read »
May 15, 2013 at 11:36 AM
Ask Ben: Print Part Of A Web Page With jQuery
I found this helpfull when you need to keep (refresh) the original parent page after closing the iframe child print dialog (Hoping you're not using a form at this time so it won't submit again): On ... read »
May 14, 2013 at 7:13 PM
What If All User Interface (UI) Data Came In Reports?
@Jonah, If there's any books you'd recommend on the subject of domain modelling, I'd love to hear it. I just downloaded the free PDF of "Domain Driven Design Quickly". Figured I'd give it ... read »
May 14, 2013 at 6:57 PM
The UX Of Prototyping: Low-Fidelity Is The New High-Fidelity
@Phillip, I'm not sure I follow what you mean? Are you saying that you looked at the list of widgets provided by the jQuery UI and let that be your style guide? ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools