使用Object.create()复制构造函数和new

Replicating constructors and new with Object.create()

本文关键字:构造函数 new 复制 Object create 使用      更新时间:2023-09-26

根据我对OOP javascript的有限经验,处理具有不同属性但方法相同的多个对象的常见方法是使用如下构造函数:

function Animal ( type ) {
    this.type = type
};
Animal.prototype.sayHello = function () {
    return 'Hi, I am a ' + this.type
};
var goat = new Animal( 'Goat' );

我在这里的理解是goat将继承/引用Animal的功能。

假设我可以用以下对象字面概念复制上面的内容:

var Animal = {
    type : '',
    sayHello : function () {
        return 'Hi, I am a ' + this.type
    }
}
var goat = Object.create( Animal );
goat.type = 'Goat';

Animal的继承在这里丢失了吗?还是Goat仍在引用方法的Animal

我想知道使用Object.create()而不是new来复制构造函数/类是否有任何问题。是否存在性能偏移或继续使用new的任何原因?

任何建议都将不胜感激,如果需要澄清,我很乐意补充这个问题。

更新的对象创建

var Animal = {
    sayHello : function () {
        return 'Hi, I am a ' + this.type
    }
}
var goat = Object.create( Animal, { 'type' : { value: 'goat' } } );

处理具有不同属性但方法相同的多个对象的常见方法是使用构造函数。。。

是的,另一种常见的方式是(正如您所看到的)Object.create

我在这里的理解是goat将继承/引用Animal的功能。

不完全是。在new Animal表达式中,goat被分配由Animal.prototype引用的对象作为其底层原型。没有Animal的直接连接,只有到Animal.prototype的连接。(在正常情况下,Animal.prototype通过其constructor属性引用回Animal,尽管如果有人将新对象分配给Animal.prototype,则该链接可能会断开。)

Animal的继承在这里丢失了吗?还是Goat仍在引用方法的Animal

在您的非构造函数示例中,goatAnimal作为其底层原型,因此对于在goat上找不到的任何属性,JavaScript引擎将查看Animal,看看it是否具有它。在您的示例中,这意味着goat使用的是Animal中的sayHello,而不是type,因为goat有自己的type

大致相当于:

function Animal ( type ) {
    this.type = type
};
Animal.prototype.sayHello = function () {
    return 'Hi, I am a ' + this.type
};
var goat = new Animal( 'Goat' );

使用Object.create设置原型看起来是这样的:

var animalPrototype = {
    sayHello: function () {
        return 'Hi, I am a ' + this.type
    }
};
function createAnimal(type) {
    var rv = Object.create(animalPrototype);
    rv.type = type;
    return rv;
};
var goat = createAnimal( 'Goat' );

回复您的评论:

createAnimal中包含animalPrototype,然后调用Object.create(this.animalPrototype),会有什么问题吗?

如果你的意思是:

function createAnimal(type) {
    var animalPrototype = {                       // Issue #1
        sayHello: function () {
            return 'Hi, I am a ' + this.type
        }
    };
    var rv = Object.create(this.animalPrototype); // Issue #2
    rv.type = type;
    return rv;
};
var goat = createAnimal( 'Goat' );

是的,有两个问题:

  1. 您需要为每次对createAnimal的调用创建一个新的animalPrototype,这会破坏目的,以及2。调用createAnimal中的this将是全局对象(宽松模式)或undefined(严格模式),因此this.animalPrototype可能不是您想要的表达式

你可以这样做:

function createAnimal(type) {
    var rv = Object.create(createAnimal.proto);
    rv.type = type;
    return rv;
};
createAnimal.proto = {
    sayHello: function () {
        return 'Hi, I am a ' + this.type
    }
};
var goat = createAnimal( 'Goat' );

当然,这可能会让人感到困惑,因为它看起来很像构造函数。