开发者

Confusion about the purpose of constructor functions

I'm a bit confused as to the purpose of constructor functions in javascript. I know that creating a constructor function through use of the new keyword also creates a new instance of a global object. Is that all one can do with them?

Also, the prototype of the new instance is the same as the global object, so why not just use the global object as many times as you need to instead of creating an instance? Can one add properties to a new instance?

Also, what points about constructor functions am I missing? Any help understanding this would be much appreciated. 开发者_开发知识库


"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.


Constructor functions are the way Javascript enables prototypical inheritance.

The prototype of the new instance is not the global object - it is the constructor's prototype property.

function MyConstructor(){
    //set member variables of the instance with
    this.x = 17;
}

MyConstructor.prototype = {
    //stuff in here will be shared by all MyConstructor objects:
    foo: function(){
        //
    },
    bar = 17;
}

var x = new MyConstructor();
//x's prototype is the MyConstructor.prototype object.
//the "new" sets the prototype magically behind the scenes.
// x can now use all attributes (and methods) of its prototype as its own:
x.foo();
//this is how OO works in Javascript - there are no "classes"

//note that overwriting a variable that is defined on the prototype overwrites
// only on the instance instead;
x.bar = 42;

vay y = new MyConstructor();
y.bar; //is still 17
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜