javascript apply, call and constuctor

Let’s first create a simple function that we will be using through the rest of this post. This function will just return an array with the current value ofthis and the two supplied arguments.

  1. <script type=“text/javascript”>
  2. function makeArray(arg1, arg2){
  3.     return [ this, arg1, arg2 ];
  4. }
  5. </script>

Most common way, unfortunately, global function calls

When we are learning JavaScript we learn how to define functions using the syntax used in the example above. We learn that it’s also very easy to call that function — all we need to do is:

  1. makeArray(‘one’‘two’);
  2. // => [ window, ‘one’, ‘two’ ]

 

In JavaScript, and I’m not talking specifically about the browser here, there’s a default/global object. It’s as if every code that we write which seems to be just “loose” inside your script (i.e. outside of any object declaration) is actually being written in the context of that global object. In our case, thatmakeArray function isn’t just a loose “global” function, it’s a method of the global object. Bringing ourselves back to the browser, the global object is mapped to the window object in this environment. Let’s prove that.

  1. alert( typeof window.methodThatDoesntExist );
  2. // => undefined
  3. alert( typeof window.makeArray);
  4. // => function

The more you leverage functions in JavaScript, the more you find yourself passing functions around and needing to invoke them in different contexts. Just like jQuery does in the event handler functions, you’ll often need to override the value of this. Remember I told you functions are objects in JavaScript? Functions have predefined methods, two of them are apply() and call(). We can use them to do precisely that kind of overriding.

  1. var gasGuzzler = { year: 2008, model: ‘Dodge Bailout’ };
  2. makeArray.apply( gasGuzzler, [ ‘one’‘two’ ] );
  3. // => [ gasGuzzler, ‘one’ , ‘two’ ]
  4. makeArray.call( gasGuzzler,  ‘one’‘two’ );
  5. // => [ gasGuzzler, ‘one’ , ‘two’ ]

The two methods are similar. The first parameter will override this. They differ on the subsequent arguments. Function.apply() takes an array of values that will be passed as arguments to the function and Function.call() takes the same arguments separately. In practice I believe you’ll find that apply() is more convenient in most cases.

JavaScript function invocation rule  If we want to override the value of this without copying the function to another object, we can usemyFunction.apply( obj ) or myFunction.call( obj ).

I won’t delve into the details of defining types in JavaScript but at minimum we should be aware that there aren’t classes in JavaScript and that any custom type needs a constructor function. It’s also a good idea to define the methods of your type using the prototype object, which is a property of the constructor function. Let’s create a small type.

  1. //declaring the constructor
  2. function ArrayMaker(arg1, arg2) {
  3.     this.someProperty = ‘whatever’;
  4.     this.theArray = [ this, arg1, arg2 ];
  5. }
  6. // declaring instance methods
  7. ArrayMaker.prototype = {
  8.     someMethod: function () {
  9.         alert( ‘someMethod called’);
  10.     },
  11.     getArray: function () {
  12.         return this.theArray;
  13.     }
  14. };
  15. var am = new ArrayMaker( ‘one’‘two’ );
  16. var other = new ArrayMaker( ‘first’‘second’ );
  17. am.getArray();
  18. // => [ am, ‘one’ , ‘two’ ]

What’s very important to note here is the presence of the new operator before the function call. Without that your function will just be called like a global function and those properties that we are creating would be created on the global object (window.) And you don’t want to do that. Another issue is that, because you typically don’t have an explicit return value in your constructor function, you’ll end up assigning undefined to some variable if you forget to use new. For these reasons it’s a good convention to name your constructor functions starting with an upper case character. This should serve as a reminder to put the new operator before the call.

With that taken care of, the code inside the constructor is very similar to any constructor you probably have written in other languages. The value ofthis will be the new object that you are trying to initialize.

JavaScript function invocation rule  When used as a constructor, like new MyFunction(), the value of this will be a brand new object provided by the JavaScript runtime. If we don’t explictly return anything from that function, this will be considered its return value.
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s