javascript - 函数构造函数和原型(prototype)构造函数有什么区别?

标签 javascript constructor prototype

我想知道这之间有什么区别

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

还有这个

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

在 JavaScript 中为原型(prototype)声明构造函数时。

与常规函数相比,使用 prototype.constructor 有什么优势?

最佳答案

看看下图,取自 following answer :

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

  1. JavaScript 将构造函数的 prototype 属性设置为原型(prototype)对象。
  2. JavaScript 将原型(prototype)对象的 constructor 属性设置为构造函数。

因此当你这样做时:

function Foo() {}

JavaScript 实际上是这样的:

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

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

var foo = new Foo;

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

function Foo() {}

Foo.bar = true;

Foo.prototype.baz = true;

var foo = new Foo;

console.log(foo.bar); // undefined

console.log(foo.baz); // true

现在在原型(prototype)上有一个 constructor 属性的好处是,当你创建一个 Foo 的实例时,该实例继承了 constructor来自原型(prototype)的属性。因此,您可以使用它来找出对象的类型:

function Foo() {}
function Bar() {}

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

test(new Foo);
test(new Bar);
test(new Object);

除此之外,原型(prototype)的 constructor 属性并没有什么特别之处。这只是一个普通的属性(property)。用 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.";

但是,关键在于它只是另一个原型(prototype)属性。事实上,我们可以利用这一优势来创建更简洁的代码。例如,这就是我们通常在 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 都是原型(prototype)函数:constructorsumdiff 分别。原型(prototype)只是一个对象,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 属性只是一个普通的原型(prototype)属性。希望这能回答您的问题。

关于javascript - 函数构造函数和原型(prototype)构造函数有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27307465/

相关文章:

javascript - 单击时显示。点击时不会隐藏

javascript - 我如何告诉 Require.js 对多个电源使用相同的路径和垫片?

运行程序时出现java.lang.NullPointerException

jquery - 为什么magento安装的scriptaculous中的effects.js与Mike Tuupola的lazy-load jquery插件冲突

JavaScript - 唯一更新原型(prototype)对象文字中的属性

javascript - 如何在谷歌字体加载时显示加载图像?

java - 在另一个字符串中找到该字符串的字符有多少次

c++ - const 成员堆栈与堆

c++ - C/C++ 函数 - 如何允许原型(prototype)?

javascript - firewatch 视差效果与上面的另一个 div 和内容