假设我有一个对象,并用它创建另一个对象:
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
会在per1
和per2
之间共享,但名称不会
另一个混淆是假设我有一个功能:
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}
他们不一样,为什么?
答案 0 :(得分:4)
Object.create
返回一个新对象,其[[Prototype]]是作为参数传递的对象。因此,per1
和per2
共享相同的原型。
现在,关于原型对象的一些事实:
当您尝试读取属性且对象没有它时,它将在原型链中查找它。因此,如果您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
电话的返回值。