Article

JavaScript Object-Oriented Programming Part 2

Page: 1 2 3 4 Next

Constructor

Every instance of an object has a constructor property. It returns the Function object that created that instance of the object. For example:

function myConstructor(){  
}  
var str = new String("Some String");  
var obj = new Object();  
var myObj = new myConstructor();  
alert(str.constructor); // the native String() constructor  
alert(String) // the native String() constructor  
alert(obj.constructor); // the native Object() constructor  
alert(Object) // the native Object() constructor  
alert(myObj.constructor); // the user-defined myConstructor() constructor  
alert(myConstructor); // the user-defined myConstructor() constructor

I recommend that you run this example to see what it returns. Notice how each alert returns the Function object that created that instance of the object. Also, notice that JavaScript's native objects return "[native code]". When you retrieve the typeof for a constructor property, you'll find that it's the same as the Function object that created it, "function":

alert(typeof str.constructor); // "function"  
alert(typeof String) // "function"  
alert(typeof obj.constructor); // "function"  
alert(typeof Object) // "function"  
alert(typeof myObj.constructor); // "function"  
alert(typeof myConstructor); // "function"

All of the above return "function". Because a constructor property returns a reference to the Function object that created it, the constructor is in fact a constructor method:

function myConstructor(){  
 var x = "y";  
 this.x = "x";  
 return x;  
}  
var myObj = new myConstructor();  
alert(myObj.constructor); // the myConstructor() function object  
alert(myObj.constructor()); // "y"

Note that in this example, we return the local variable, x, rather than the object's property, this.x. So, if every object has a constructor method, and every method is really a Function object, what's a Function object's constructor?

alert(myConstructor.constructor);  
alert(myObj.constructor.constructor);  
alert(myConstructor.constructor.constructor);  
alert(myObj.constructor.constructor.constructor);

All of those return the native Function() object constructor. Although that's trivial, I personally thought it rather interesting- and thought you might too, and it brings me to another point. Constructors are both "types of objects" as well as objects themselves (more specifically, Function objects). Thus, Date is both an object (a Function object) and a "type of object", from which you can create Date objects, or instances of the Date object. This is true for all native objects and user-defined objects.

The practical value of all this is that, via an object's constructor method, we can figure out what type of object it is. We can see whether it's a String object, created from the native String constructor function; whether it's an Object object, created from the native Object constructor function; or whether it's one of our user-defined objects, created from a user-defined constructor function.

Besides being a method of an object, constructor() is also a method of a primitive data type. So what does it return? After all, no real constructor function was run to create primitive data types:

var primitiveString1 = "This is a primitive string";  
var primitiveString2 = String("This is a primitive string");  
var stringObject = new String("This is a String object");  
primitiveString1.prop = "This is a property";    
primitiveString2.prop = "This is a property";  
stringObject.prop = "This is a property";  
alert(primitiveString1.prop) // "undefined"  
alert(primitiveString2.prop) // "undefined"  
alert(stringObject.prop) // "This is a property"  
alert(typeof primitiveString1); // "string"  
alert(typeof primitiveString2); // "string"  
alert(typeof stringObject) // "object"  
alert(primitiveString1.constructor); // "function String(){    
[native code] }"  
alert(primitiveString2.constructor); // "function String(){    
[native code] }"  
alert(stringObject.constructor); // "function String(){    
[native code] }"

As we can see, both a String primitive data type and a String object have the same constructor(), the native String() constructor. Note that constructor() is the only property/method that a primitive data type holds, so these data types have access to the properties/methods defined in the native object constructor function. For example, a primitive String data type (as well as a String object) has access to the many properties/methods defined in the native String() constructor, including:

  • length
  • anchor()
  • big()
  • bold()
  • charAt()
  • charCodeAt()
  • concat()
  • indexOf()
  • lastIndexOf()
  • sub()
  • substr()
  • substring()

However, a String object may also contain properties/methods that are particular to that object. For example:

var myStringObj = new String("This is a String object");  
myStringObj.prop = "This is a property of the object I created";  
alert(myStringObj.prop) // "This is a property of the object I created"

As Alex Vincent notes, sometimes you'll want to turn a primitive data type into an object. For example, let's say we have a function like this:

function myFunc(param){  
 param.property = "I want to add this property";  
 alert(param.property); // "undefined"  
}

If we decide to use this function and pass it a primitive data type, we can't also add properties to it, because it's not an object. And anyway, passing an object is rather cumbersome:

myFunc(new String("This is a String object"));  
myFunc(new Number(5));

One way to overcome this, as Alex points out, is as follows:

function myFunc(param){  
 param = new param.constructor(param);  
 param.property = "I want to add this property";  
 alert(param.property); // returns "I want to add this property"  
}

That new line looks confusing, but let's take a step back. Imagine that we wanted to change a primitive Number into a new Number object. We could use:

var myNum = 5;  
myNum = new Number(5);

Now let's take that a step further:

var myNum = 5;  
myNum = new myNum.constructor(5);

You must remember that myNum.constructor() is the same as Number(). Then, instead of using 5, we can use myNum, as that, too, is 5:

var myNum = 5;  
myNum = new myNum.constructor(myNum);

And the same works for a String primitive data type - as it does for all primitive data types. Therefore, when we pass any primitive data type as an argument to our function, we automatically convert it to an object so that we can add properties/methods to it.

If you liked this article, share the love:
Print-Friendly Version Suggest an Article

Sponsored Links