Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.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 正在使用Object.create()复制构造函数和新对象_Javascript_Oop - Fatal编程技术网

Javascript 正在使用Object.create()复制构造函数和新对象

Javascript 正在使用Object.create()复制构造函数和新对象,javascript,oop,Javascript,Oop,根据我对OOP javascript的有限经验,处理具有不同属性的多个对象的常见方法是使用构造函数,如下所示: function Animal ( type ) { this.type = type }; Animal.prototype.sayHello = function () { return 'Hi, I am a ' + this.type }; var goat = new Animal( 'Goat' ); 我的理解是,山羊将继承/参考动物的功能 我假设我可以用

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

function Animal ( type ) {
    this.type = type
};
Animal.prototype.sayHello = function () {
    return 'Hi, I am a ' + this.type
};
var goat = new Animal( 'Goat' );
我的理解是,
山羊
将继承/参考
动物
的功能

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

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

我的理解是,
山羊
将继承/参考
动物
的功能

不完全是。在
new Animal
表达式中,
goat
Animal.prototype
引用的对象指定为其基础原型。与
动物
没有直接联系,只与
动物原型
有直接联系。(
Animal.prototype
通过其
constructor
属性引用回到
Animal
,但如果有人将新对象分配给
Animal.prototype
,该链接可能会断开)

Animal
的继承在这里丢失了,还是
Goat
仍然引用
Animal
作为方法

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

大致相当于:

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' );
…那么是的,有两个问题:

  • 每次调用
    createAnimal
    ,您都会创建一个新的
    animalPrototype
    ,这会破坏目的,2
    调用
    createAnimal
    中的此
    将是全局对象(松散模式)或
    未定义的
    (严格模式),因此
    此.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' );
    

    当然,这可能会让人困惑,因为它看起来非常像一个构造函数。

    +1非常好和客观地总结了正在发生的事情。OP-总之是的,使用
    Object.create
    可以在JavaScript中执行原型继承。它将创建一个新对象,其原型就是您指定的原型。(顺便说一句,我选择了“大多数情况下更喜欢的对象。创建”)@BenjaminGruenbaum:谢谢!我的观点相当平衡。如果我正在创建感觉“优雅”的东西,我会使用构造函数(通过我的浏览器)。但是我一直使用
    Object.create
    ,我只需要一个与另一个特定对象基本相同但略有不同的对象。我有一个项目,我们经常这样做,虽然它可以用构造函数来完成,但它会非常笨重。我发现它们都是非常有用的工具。我喜欢JavaScript的灵活性。@T.J.Crowder非常感谢你的回答,它澄清了我的几个问题。我更新了我的问题删除偏好,因此您可能需要更新答案的开头。再次感谢你@再次感谢T.J.克劳德。在
    createAnimal
    中是否会出现任何问题,包括
    animalPrototype
    ,然后调用
    Object.create(this.animalPrototype)
    ?只是为了组织?也许是个愚蠢的主意。@mikedidthis:请参阅答案末尾的进一步更新。您真的想在所有呼叫站点键入
    山羊。键入
    (及更多)?如果你想改变它,重构会更困难。这太可怕了。在有人说“创建工厂”之前,在这种情况下,您只是在做美化的构造函数+原型。@Esailija我添加了一个关于如何填充
    类型的更新。我很想知道你是如何处理这个问题的。这比我刚才批评的还要糟糕:它仍然在调用站点,在对象外部,甚至更多verbose@Esailija你能否澄清原因,不仅仅是为了我自己的理解,也是为了其他用户?我需要创建多个对象。它们之间唯一的区别是
    类型
    。在下面的答案中,
    function CreateAnimal(type)
    是否更适合您?如有进一步评论,我将不胜感激。谢谢。
    var a=new Animal(type)
    vs
    var a=CreateAnimal(type)
    ?两者都很方便,可以将财产分配放在它们所属的地方。然而,在声明站点上,代码仍然有点难看,您必须显式创建并返回一个对象-当使用普通构造函数时,创建和返回语句是隐式的->这就是为什么您只在普通构造函数中键入
    this.type=xxx
    ,但需要在工厂中键入return语句和object.create。