函数构造函数和原型构造函数之间有什么区别?

时间:2014-12-05 01:45:16

标签: javascript constructor prototype

我想知道这个

之间有什么区别
 MyClass = function() {};
 MyClass.prototype.Foo = function();

和这个

 MyClass = {};
 MyClass.prototype.constructor = function() {};
 MyClass.prototype.Foo = function();

在JavaScript中声明原型的构造函数时。

使用prototype.constructor优于常规函数有什么好处?

2 个答案:

答案 0 :(得分:6)

查看以下图片,取自following answer

当您创建新函数时,JavaScript也会自动创建一个新对象(原型):

  1. JavaScript将构造函数的prototype属性设置为原型对象。
  2. JavaScript将原型对象的constructor属性设置为构造函数。
  3. 因此当你这样做时:

    function Foo() {}
    

    JavaScript实际上是这样做的:

    function Foo() {}
    Foo.prototype = { constructor: Foo };
    

    为什么JavaScript会这样做?考虑一下创建Foo的实例时会发生什么:

    var foo = new Foo;
    

    使用Foo关键字创建new的实例时,JavaScript实际上会创建Foo.prototype而非Foo的实例。这意味着foo继承了Foo.prototype而非Foo的属性。为了明确这一点:

    
    
    function Foo() {}
    
    Foo.bar = true;
    
    Foo.prototype.baz = true;
    
    var foo = new Foo;
    
    alert(foo.bar); // undefined
    
    alert(foo.baz); // true
    
    
    

    现在,在原型上具有constructor属性的优点是,当您创建Foo的实例时,该实例将从原型继承constructor属性。因此,您可以使用它来找出对象的类型:

    
    
    function Foo() {}
    function Bar() {}
    
    function test(obj) {
        switch (obj.constructor) {
        case Foo: alert("It's a Foo."); break;
        case Bar: alert("It's a Bar."); break;
        default: alert("It's something else.");
        }
    }
    
    test(new Foo);
    test(new Bar);
    test(new Object);
    
    
    

    除此之外,原型的constructor属性并没有什么特别之处。它只是一个普通的财产。用Tyler Durden的话来说:https://www.youtube.com/watch?v=4X2AvfSTi6Q

    由于它是一个普通的属性,你可以决定根本没有构造函数属性:

    function Foo() {}
    Foo.prototype = {}; // no constructor property
    

    你可以决定让它指向其他一些功能:

    function Foo() {}
    function Bar() {}
    Foo.prototype.constructor = Bar;
    

    您可以决定使其指向功能以外的其他内容:

    function Foo() {}
    Foo.prototype.constructor = "I am not a function.";
    

    然而,重点是它只是另一个原型属性。实际上,我们可以利用它来创建更清晰的代码。例如,这就是我们通常创建"类"在JavaScript中。

    function MyClass(a, b) {
        this.a = a;
        this.b = b;
    }
    
    MyClass.prototype.sum = function () {
        return this.a + this.b;
    };
    
    MyClass.prototype.diff = function () {
        return this.a - this.b;
    };
    

    它不是很干净。但请注意,所有三个函数MyClasssumdiff都是原型函数:constructorsumdiff。原型只是一个对象,JavaScript中的对象文字提供了一种很好的封装形式。我们可以利用这个来编写更清晰的代码:

    function defclass(prototype) {
        var constructor = prototype.constructor;
        constructor.prototype = prototype;
        return constructor;
    }
    
    var MyClass = defclass({
        constructor: function (a, b) {
            this.a = a;
            this.b = b;
        },
        sum: function () {
            return this.a + this.b;
        },
        diff: function () {
            return this.a - this.b;
        }
    });
    

    那更清洁了。此外,它向我们展示了constructor属性只是一个普通的原型属性。希望能回答你的问题。

答案 1 :(得分:0)

MyClass.prototype.Foo = function(); 此代码为类MyClass添加一个静态函数,这意味着它的实例可以通过点运算符来识别Foo函数。 当我们做新的MyClass时,首先,我们创建一个像{}这样的空白对象,然后我们调用对象上的构造函数(MyClass.prototype.constructor.apply(obj,args)),最后,我们设置了原型MyClass到对象的原型并返回对象。 因此,当您编写" MyClass.prototype.constructor = function(){}"时,上面的第二步将不执行任何操作。