prototype.constructor和它自身的对象有什么区别?

时间:2016-09-21 14:35:33

标签: javascript oop

我正在尝试理解面向对象的JavaScript并坚持使用一些示例。它们似乎是一种不同的传统OOP。

首先,与那些有什么区别:

function Foo()
{
    this.bar = function ()
    {
        // ...
    };
}

VS

function Foo() {}

Foo.prototype.bar = function()
{
    // ...
}

另外,我应该使用哪一个?哪一个是正确的方式?

工厂模式的另一个例子。

function Circle()
{
    this.say = function() { console.log('I am circle.'); };
}

function Square()
{
    this.say = function() { console.log('I am square.'); };
}

function chooseShape(decision)
{
    var shape = null;

    if (decision === "Circle")
    {
        shape = Circle; // or Circle.prototype.constructor;
    } else if (decision === "Square")
    {
        shape = Square; // or Square.prototype.constructor;
    }

    return new shape();
}

如果我用这些改变这些行:

if (decision === "Circle")
{
    shape = Circle.prototype.constructor;
} else if (decision === "Square")
{
    shape = Square.prototype.constructor;
}

他们按预期工作,但我想知道幕后发生了什么。

4 个答案:

答案 0 :(得分:2)

原型上的函数只创建一次并在每个实例之间共享。在构造函数中创建的函数将作为使用构造函数创建的每个新对象的新对象创建。

作为一般规则,函数应该在原型上,因为它们通常不会针对相同类型的不同对象进行修改,并且这具有轻微的内存/性能优势。除非要创建共享的静态属性,否则应在构造函数中定义对象和数组等其他属性,在这种情况下,您应该使用原型。

希望这能回答你的问题

答案 1 :(得分:1)

这些例子可以解释不同之处:

// constructor function
function Person(first, last) {
    this.firstName = first;
    this.lastName = last;

    this.hey = function() { ... }
}

var person1 = new Person("Frank", "Sinatra")

// add a method to each person instance
Person.prototype.name = function() {
    return this.firstName + " " + this.lastName
};

person1.name() // "Frank Sinatra"

Prototype允许您将 new 属性添加到构造函数及其实例中。

另一个区别是Prototype是在类级别定义的,构造函数中的属性是在实例级别上。因此name()只定义一次,而this.hey将为每个实例定义。

答案 2 :(得分:0)

1。 在第一种情况下,每次创建新对象时都会创建新函数,并将此函数放入对象的属性中。在第二种情况下,您只需创建一次函数并将其放入原型。

这两种情况都会导致方法barFoo的每个实例上都可调用。 “正确的方法”是将方法定义放在原型中(即第二种情况);但是如果有一些特定于实例的变量不想放入实例对象,则可以在每次创建对象时创建一个函数。但请记住,这将花费你更多的记忆。

2。 没有区别。 CircleSquare应指向与Circle.prototype.constructorSquare.prototype.constructor相同的功能。你可以自己看看:

> Circle.prototype.constructor === Circle
< true

答案 3 :(得分:-1)

创建Foo实例的第一种方法是使用函数构造函数并调用new:

function Foo()
{
    this.bar = function ()
    {
        // ...
    };
}

如果通过调用new运算符创建Foo实例,如下所示:

var foo= new Foo();

然后对于每个创建的对象都会创建一个新的bar方法。

或者,使用prototype属性,创建的所有Foo对象都不会创建单独的bar方法。相反,他们将从原型继承bar。因为现在只有一个bar的副本,显然这种方式更有效。