关于构造函数的目的的困惑

时间:2011-08-02 16:06:53

标签: javascript

我对javascript中构造函数的目的有点困惑。我知道通过使用new关键字创建构造函数也会创建一个全局对象的新实例。这是所有人都可以做到的吗?

此外,新实例的原型与全局对象相同,那么为什么不只是根据需要使用全局对象而不是创建实例?可以为new实例添加属性吗?

另外,我错过了关于构造函数的要点?任何帮助理解这一点将非常感激。

2 个答案:

答案 0 :(得分:3)

  

“我知道通过使用new关键字创建构造函数也会创建一个全局对象的新实例。”

那不对。 使用new调用函数创建一个新对象,但它不是全局对象。它是该函数的一个实例,并将该函数作为其.constructor引用。

prototype只是构造函数的所有实例指向的对象。它允许您的所有实例引用一组通用属性。

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

编辑:以下是一个非常简单的DOM包装示例:

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

构造函数在从它创建的每个实例上放置一个单独的count属性初始化为0

如果您将构造函数传递给String,它将自动调用fetchById上的prototype。否则,您可以在返回新实例后直接调用fetchById()

成功getElementById后,fetchById会存储在该实例的element属性中找到的元素,并调用setup方法,该方法存储click元素的.listener属性上的事件侦听器,并使用它来向元素添加click事件侦听器。

侦听器只是递增该实例的计数器,并将新计数附加到元素。

count到达10后,会调用tear_down方法删除侦听器。

答案 1 :(得分:0)

构造函数是Javascript启用原型继承的方式。

新实例的原型是而不是全局对象 - 它是构造函数的prototype属性。

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