首先您需要了解原型是什么。
在 Javascript 中,几乎一切都是对象。
编辑(感谢@Mathletics):
原始布尔值、数字和字符串不是对象
当您在 Javascript 中创建对象时,默认情况下,其原型将是 Object。
所以,如果我这样做:
var obj = {};
console.log(obj.__proto__)
这会产生:
对象{}
暂停:
要了解obj.prototype 和obj.__proto__ 之间的区别,请参阅此thread。
接下来要了解prototype chaining的概念。
这就是 Javascript 中继承的结构。基本上,原型是另一个对象的“父对象”,它从中派生出方法和属性。
想象一个Rabbit 继承自Mammal 的方案,Mammal 继承自Animal。在 Javascript 原型链中表示它就像:
(Rabbit) -> (Mammal) -> (Animal) -> (Object) -> null
带代码:
function Animal(){}
function Mammal(){}
function Rabbit(){}
Mammal.prototype = new Animal();
Rabit.prototype = new Mammal();
如果您能够理解这些概念,您可能会自己找到问题的答案,但我会尽量说得更清楚:
1)为什么以下一个是假的,另一个是真的?
User.prototype.hasOwnProperty('name'); // false
User.hasOwnProperty('name'); // true
你应该阅读hasOwnProperty method reference:
从 Object 派生的每个对象都继承了 hasOwnProperty 方法。该方法可用于确定一个对象是否具有指定属性作为该对象的直接属性[...]
这是一种确保您要查找的属性是在对象本身中定义的方法,而不是在原型链的更深处。
一个相反的例子是:
console.log(User.hasOwnProperty('constructor'));
由于constructor 属性在原型链中定义得更深,它不是User 对象的“自己的属性”。
在您的情况下,name 是在您的 User 对象中定义的属性,但未在全局 Object 的上下文中定义。
2) 以下有什么区别:
User.constructor;
User.prototype.constructor;
第一个like取User的构造函数,第二个取其原型的构造函数(在本例中为全局Object)。
3) User.constructor 和
User.prototype.constructor 如果我覆盖原型属性,例如
这个:
User.prototype = {
changeName: function(newName) {
this.name = newName;
}
};
请阅读此thread。
TL;DR:当你直接使用原型时,你正在打破原型链并创建一个新的。在Rabbit 示例中,如果您在某个时候这样做了:
Rabbit.prototype = {
// ...
};
您的新原型链将是:
(Rabbit) -> (Object) -> null
因此,在您的第一个示例中,User.prototype.constructor 会产生:
函数对象{}
在你的第二个例子中,它会产生:
函数用户(名称)
知道了吗?
4) User 是函数还是原型还是什么?
User 是一个对象,其原型为Function 对象,其原型为Object 对象。
画出来:
(User) -> (Function) -> (Object) -> null
希望我已经说清楚了。