Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript prototype.constructor和它本身的对象有什么区别?_Javascript_Oop - Fatal编程技术网

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

Javascript prototype.constructor和它本身的对象有什么区别?,javascript,oop,Javascript,Oop,我正在努力理解面向对象的JavaScript,并坚持使用一些示例。它们似乎有点不同于传统的面向对象编程 首先,这两者有什么区别吗 function Foo() { this.bar = function () { // ... }; } vs 还有,我应该用哪一个?哪一个是正确的方法 在工厂模式的另一个示例中 function Circle() { this.say = function() { console.log('I am circle

我正在努力理解面向对象的JavaScript,并坚持使用一些示例。它们似乎有点不同于传统的面向对象编程

首先,这两者有什么区别吗

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

还有,我应该用哪一个?哪一个是正确的方法


在工厂模式的另一个示例中

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;
}

它们按预期工作,但我想知道引擎盖下发生了什么。

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

一般来说,函数应该在原型上,因为它们通常不会针对同一类型的不同对象进行修改,这对内存/性能有一点好处。其他属性(如对象和数组)应该在构造函数中定义,除非您想要创建共享的静态属性,在这种情况下,您应该使用原型

希望这能回答你的问题。 在第一种情况下,每次创建新对象时都要创建新函数,并将此函数放入对象的属性中。在第二种情况下,只需创建一次函数并将其放入原型中

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

二,。 没有区别
Circle
Square
应该指向与
Circle.prototype.constructor
Square.prototype.constructor
相同的函数。你可以自己看:

> Circle.prototype.constructor === Circle
< true
>Circle.prototype.constructor===Circle
创建Foo实例的第一种方法是使用函数构造函数并调用new:

function Foo()
{
    this.bar = function ()
    {
        // ...
    };
}
如果通过调用新操作符创建Foo实例,如下所示:

var foo= new Foo();
然后,对于像这样创建的每个对象,都将创建一个新的bar方法


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

这些示例可以解释这种差异:

// 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允许您向构造函数及其实例添加新的属性


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

您的第一个问题(您已经问了两个)将由@JamesThorpe涵盖哦,对不起。事实上,我在提问之前已经搜索过了,但什么也没找到。非常感谢。引擎盖下什么也没发生。构造函数的原型有一个指向构造函数本身的构造函数属性。打印出来贴在墙上。
// 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"