0

假设我有一个对象,并用它创建另一个对象:

var person = {
    name: "Lee",
    age: "12",
    others: {}
}

var per1 = Object.create(person);
var per2 = Object.create(person);

per2.name = "Mike";
per2.others.hello = "world";

console.log(per1); // Object {name: "Lee", age: "12", obj: Object}
console.log(per2); // Object {name: "Mike", name: "Lee", age: "12", obj: Object}

console.log(per1.others.hello, per2.others.hello) // world world

我的困惑是:

  • 为什么per2有双名?如果另一个来自原型,我试着per2.prototype.name = "mike"告诉我原型是未定义的,但那怎么可能是未定义的呢?的工作Object.create不是Creates a new object with the specified prototype object and properties. MDN

  • 为什么会在两者之间others共享但名称不共享per1per2

另一个困惑是假设我有一个功能:

function Person(name) {
    this.name = name
}
Person.prototype.say = function () {
    console.log("hello")
}

但是从函数创建另一个对象,没有函数的原型:

var obj = Object.create(Person);

console.log(obj) // Function {}:
console.log(obj.prototype) // undefined

为什么原型未定义?不是自己Object.create创造的吗?

更新:

正如@bfavaretto 所说,只有构造函数可以拥有prototype,并且Object.getPrototypeOf可以显示一个对象的原型。所以我尝试了这两种方法来获取per1的原型:

console.log(per1.constructor.prototype) // Object{}
console.log(Object.getPrototypeOf(per1)) //Object {name: "Lee", age: "12", obj: Object}

他们是不同的,为什么?

4

2 回答 2

4

Object.create返回一个新对象,其 [[Prototype]] 是作为参数传递的对象。所以两者都per1共享per2同一个原型。

现在,关于原型对象的一些事实:

  • 当你尝试读取一个属性而对象没有它时,它会在原型链上查找它。所以如果你console.log(per1.name)'name' 不是在 上per1,而是在它的原型上。

  • 但是,当您尝试写入不存在的属性时,它只是在对象本身上创建,而不是在其原型上。因此,per2.name = "Mike";在 上创建了一个新的“名称”属性per2,并从原型中隐藏了该属性。由于某种原因,Chrome 控制台决定同时记录两者,但在实际使用中,只有“Mike”是可读的。

以上应该回答你的第一个问题。第二个是相关的,但也与对象在 js 中的工作方式有关。person.others是一个对象。per2.others是对该确切对象的引用。相同的引用由 共享per1,这就是为什么您会看到两次“世界”。“name”不会发生这种情况,因为它是一个字符串,一个原始值,不像others.

回答你的最后一个问题:只有函数(构造函数)才有prototype属性。new Person使用继承自 创建的对象Person.prototype,但它们的原型对象只能通过非标准obj.__proto__Object.getPrototypeOf(obj)(旧浏览器不支持)访问。

于 2013-07-29T02:26:53.747 回答
1

thing.prototype不是事物的原型。我不知道标准 ECMAScript 是否提供了访问对象原型的任何方法,但thing.__proto__往往会起作用。

对于函数,f.prototype是用new f(). 当我尝试你Object.create(Person);的东西时,它似乎有效:

console.log(obj.prototype)
>Person {say: function}
// prototype property inherited from Person function

也许您是在 Chrome Javascript 控制台中执行此操作的,而您undefined在实际记录结果之后出现时感到困惑。console.log这就是调用的返回值。

于 2013-07-29T02:21:27.133 回答