"I know that creating a constructor function through use of the new keyword also creates a new instance of a global object."
That's not right. Invoking a function with new
create a new object, but it's not global. It's an instance of that function, and will have that function referenced as its .constructor
.
The prototype
is simply the object that all the instances of the constructor function point to. It lets all your instances reference a common set of properties.
The prototype
is simply the object to which all the instances created by the constructor function contain an implicit pointer. It lets all your instances reference a common set of properties.
"Can one add properties to a new instance?"
Yes, they will be added to the object that was created from the constructor and not to its prototype.
function MyConstructor( arg ) {
// If you invoke this with "new",
// then "this" will be a reference to the new instance that is returned
this.instance_prop = arg;
}
MyConstructor.prototype.proto_prop = "baz";
var inst1 = new MyConstructor( "foo" );
var inst2 = new MyConstructor( "bar" );
console.log( inst1.instance_prop ); // foo
console.log( inst1.proto_prop ); // baz
console.log( inst2.instance_prop ); // bar
console.log( inst2.proto_prop ); // baz
EDIT: Here's an example that is a very simple DOM wrapper:
http://jsfiddle.net/CEVwa/
// constructor
var DOMWrapper = function(id) {
// initialize a count property for the instance created
this.count = 0;
// if a String was passed to the constructor, go head and call fetchById
if (typeof id === 'string') {
this.fetchById(id);
}
};
// fetches an element by the ID given, and calls the .setup() method
DOMWrapper.prototype.fetchById = function(the_id) {
// store the element with this instance
this.element = document.getElementById(the_id);
if( this.element != null ) {
this.setup();
}
};
// stores a function on the .listener property that is passed to
// addEventListener. When clicked, the counter is incremented, and
// appended to the element.
DOMWrapper.prototype.setup = function() {
if (this.element != null) {
// retain a reference to this instance that the listener can use
var wrapper = this;
// store the listener with this instance
this.listener = function() {
wrapper.count++;
wrapper.element.appendChild(
document.createTextNode( ' ' + wrapper.count )
);
// when count is 10, call the tear_down method for this instance
if( wrapper.count === 10 ) {
wrapper.tear_down();
}
};
this.element.addEventListener('click', this.listener, false);
} else {
this.no_element();
}
};
DOMWrapper.prototype.no_element = function() {
alert("you must first fetch an element");
};
// remove the listener that is stored on the .listener property
DOMWrapper.prototype.tear_down = function() {
if (this.element != null) {
if( typeof this.listener === 'function' ) {
this.element.removeEventListener('click', this.listener );
}
} else {
this.no_element();
}
};
<div id="one">element number one</div>
<div id="two">element number two</div>
var wrapper1 = new DOMWrapper(); // constructor with no arguments
wrapper1.fetchById("one"); // you must fetch the element manually
var wrapper2 = new DOMWrapper( "two" ); // with a string, it will fetchById for you
The constructor places a separate count
property initialized to 0
on each instance that is created from it.
If you pass the constructor a String, it will automatically call the fetchById
that is on the prototype
. Otherwise you can call fetchById()
directly after the new instance is returned.
Upon a successful getElementById
, the fetchById
stores the element found on the element
property of that instance and calls the setup
method, which stores click
event listener on the .listener
property of the element, and adds uses it to add a click
event listener to the element.
The listener just increments the counter for that instance, and appends the new count to the element.
Once the count
reaches 10
, the tear_down
method is called to remove the listener.