使用Object.create(),范例应该将方法附加到它们的'prototype'财产

Using Object.create(), should exemplars have methods attached to their 'prototype' property?

本文关键字:财产 prototype 方法 create Object 范例 使用      更新时间:2023-09-26

我一直在读我的JavaScript's "new"关键词被认为有害?以及这篇关于使用原型继承而不是"new"的Adobe文章。Adobe文章中有一个"新"示例:

function Foo() {
    this.name = "foo";
}
Foo.prototype.sayHello = function() {
    alert("hello from " + this.name);
};

…替换为:

var foo = {
    name: "foo",
    sayHello: function() {
        alert("hello from " + this.name);
    }
};

这里的'sayHello'方法没有附加到对象的prototype。这是否意味着'sayHello'在内存中不必要地重复(我知道V8避免这种情况,但在旧的JS引擎中,例如),因为它被复制到从foo继承的所有对象?

应该是:

var foo = {
    name: "foo",
    prototype: {
        sayHello: function() {
            alert("hello from " + this.name);
        }
    }
};

或类似的吗?

方法不附加到原型,因为这个对象成为附加到使用Object.create新创建的对象的原型。你不需要原型的原型

请记住,Object.create不会深度克隆对象。相反,它相当于

之类的内容。
Object.create = function(proto) {
   function F() {}
   F.prototype = proto;
   return new F();
}

(实际实现更复杂,但这个简短的版本说明了这个想法)

所有新创建的对象都"继承"了作为原型的foo的方法,这里没有重复。

不,如果你使用它作为原型创建另一个对象,它不会被复制。使用Object.create的几乎相同的代码实际上略有不同,您没有使用原型,您只是创建一个对象。要使用原型继承,请执行以下操作。请注意,使用new仍然会设置原型链,因此您链接到的文章的标题不是非常准确,并且您仍然在单个对象上共享属性。

var foo = {
    name: "foo",
    sayHello: function() {
        alert("hello from " + this.name);
    }
};
var extended = Object.create(foo);
var extended2 = Object.create(foo);
extended.name = "first";
extended2.name = "second";
extended.sayHello();  // hello from first
extended2.sayHello(); // hello from second
// Methods are shared, outputs true
console.log(extended.sayHello === extended2.sayHello)
// Now if you delete the property again, it will go up the chain
delete extended.name;
extended.sayHello(); // hello from foo

你也可以直接写

var extended = Object.create(Foo.prototype);

如果您创建构造函数来获取新实例而不是Object.createnew Foo,则会重复

function createFoo() {
    return {
        name: "foo",
        sayHello: function() {
             alert("hello from " + this.name);
        }
    }
}
var a = createFoo();
var b = createFoo();
 // The function objects are not shared    
alert('Are functions the same? ' + a.sayHello === b.createFoo);
如果使用闭包方法创建对象,

也不会被共享。Crockford建议创建真正的私人会员。我不使用它,因为它不使用原型链,继承很难实现,而不只是复制属性。

Function Foo() {
    var name = 'foo';
    this.sayHello = function () {
        alert(name);
    };
    this.setName = function (newName) {
        name = newName;
    };
}
var a = new Foo();
var b = new Foo();
console.log(a.sayHello === b.sayHello); // outputs false

在这里回答我自己的问题,作为我自己的笔记,也帮助向别人解释:

。使用Object.create(),范例应该有附加到它们的prototype属性的方法吗?

。不,因为Object.create(parentObject)本身将parentObject设置为动态创建的构造函数的prototype

Also: prototype始终是构造函数的属性,而不是普通对象的属性。如:

var someArray = [];
someArray.__proto__ === Array.prototype

object .create()动态地创建构造函数,在其第一个参数中将它们的原型设置为对象。