在javascript中混淆Object.create

时间:2013-07-29 02:16:46

标签: javascript object prototype

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

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的原型:< / p>

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

他们不一样,为什么?

2 个答案:

答案 0 :(得分:4)

Object.create返回一个新对象,其[[Prototype]]是作为参数传递的对象。因此,per1per2共享相同的原型。

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

  • 当您尝试读取属性且对象没有它时,它将在原型链中查找它。因此,如果您console.log(per1.name),则在per1上找不到“名称”,而是在其原型上找到“。”

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

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

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

答案 1 :(得分: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电话的返回值。