JavaScript中的原型属性和继承

JavaScript中的原型属性和继承,javascript,prototype,Javascript,Prototype,JavaScript中的原型属性和继承对我来说并不清楚 我有一个功能: function User (name) { this.name = name; } 问题: 1为什么下列一项为假,另一项为真 User.prototype.hasOwnProperty('name'); // false User.hasOwnProperty('name'); // true User.prototype.hasOwnProperty('name'); // false User.hasOwn

JavaScript中的原型属性和继承对我来说并不清楚

我有一个功能:

function User (name) {
    this.name = name;
}
问题:

1为什么下列一项为假,另一项为真

User.prototype.hasOwnProperty('name'); // false
User.hasOwnProperty('name'); // true
User.prototype.hasOwnProperty('name'); // false
User.hasOwnProperty('name'); // true
2以下各项之间有什么区别:

User.constructor;
User.prototype.constructor;
User.constructor;
User.prototype.constructor;
3如果我像这样重写prototype属性,User.constructor和User.prototype.constructor会发生什么情况:

User.prototype = {
    changeName: function(newName) {
        this.name = newName;
    }
};
User.prototype = {
    constructor: User,
    changeName: function(newName) {
        this.name = newName;
    }
};
如果我这样覆盖它会怎么样:

User.prototype = {
    changeName: function(newName) {
        this.name = newName;
    }
};
User.prototype = {
    constructor: User,
    changeName: function(newName) {
        this.name = newName;
    }
};
4用户是功能还是原型还是什么?以下网站将其称为原型:“以下示例创建了一个原型…”

非常感谢你的回答

1为什么下列一项为假,另一项为真

User.prototype.hasOwnProperty('name'); // false
User.hasOwnProperty('name'); // true
User.prototype.hasOwnProperty('name'); // false
User.hasOwnProperty('name'); // true
prototype对象没有被赋予name属性,并且默认情况下它没有name属性,因为用户不是本地用户,所以这对于prototype是错误的。 构造函数用户是一个函数,您已经将函数的名称定义为User。这是在解释函数对象时设置的。 您确定没有将其与新用户“foo”混淆。hasOwnProperty“name”;//是吗

在最后一种情况下,User的实例有一个name属性,它是由构造函数用户设置的foo

2以下各项之间有什么区别:

User.constructor;
User.prototype.constructor;
User.constructor;
User.prototype.constructor;
构造函数是函数,因为用户是函数。 未定义User.prototype.constructor,但您通常会在用户处引用它。这是以后将作为new User.constructor访问的内容;//使用者 3如果覆盖原型[…],User.constructor和User.prototype.constructor会发生什么情况

在这两种情况下,User.constructor都不会发生任何变化

对于User.prototype.constructor,之前没有定义

因此在第一种情况下仍然没有定义 在第二种情况下设置为User 请注意,在这两种情况下,整个原型现在都指向不同的对象,因此现有实例将看不到这些更改,并且新实例将无法再访问以前的原型链

4用户是功能还是原型还是什么

用户是一个函数,也是一个构造函数。在JavaScript中,如果将使用某些函数构造函数来构建构造实例,我们将它们称为构造函数

看一个更抽象的例子可能会对你有所帮助

// A function `Foo` which will be our Constructor
function Foo(baz) {
    this.bar = baz;
}

// notice here we have `Foo.name; // "Foo"`

// Setting up reference to the constructor through the prototype
Foo.prototype.constructor = Foo;
// Setting up reference to some other shared property through the prototype
Foo.prototype.fizz = ['buzz'];
然后使用

var foo = new Foo('hello world');
foo.bar; // "hello world" (own)
foo.fizz; // ["buzz"] (inherited)
foo.constructor; // Foo (inherited)

var bar = new Foo();
foo.fizz === bar.fizz; // true, this is the same Object reference - it is shared

不要害怕在你的控制台上尝试

JS中的所有内容都是对象

因此,函数是一种特殊类型的对象,该类型的对象有一个名为name的属性,这就是User.hasOwnPropertyname返回true的原因。它与同一函数可以创建的用户对象的属性无关。试着叫它别的名字,你会发现情况就是这样

任何对象都源自另一个对象,即它的原型。函数的原型具有构造函数属性和_proto__属性,但没有名称属性。 因此,Ùser.prototype.hasOwnPropertyname`应该返回false


由于原型的所有属性都是派生的,因此您可以执行此User.constructor,即使User.hasOwnPropertyconstructor将返回false,您首先需要了解原型是什么

在Javascript中,几乎所有东西都是对象

编辑谢谢@Mathletics:

基本布尔、数字和字符串不是对象

在Javascript中创建对象时,默认情况下,其原型将是一个对象

因此,如果我这样做:

var obj = {};
console.log(obj.__proto__)
这将产生:

对象{}

暂停:

要了解obj.prototype和obj.\uuuu proto\uuuuu之间的区别,请参考此

下一步是要理解的概念

这就是Javascript中继承的结构。基本上,原型是另一个对象的父对象,从中派生方法和属性

想象一个兔子继承哺乳动物的计划,哺乳动物继承动物。在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
User.prototype.hasOwnProperty('name'); // false
User.hasOwnProperty('name'); // true
你应该阅读:

从对象派生的每个对象都继承hasOwnProperty方法。此方法可用于确定对象是否具有指定的属性作为该对象的直接属性[…]

这是一种确保您要查找的属性是在对象本身中定义的,而不是在原型链的更深处

相反的例子是:

console.log(User.hasOwnProperty('constructor'));
(Rabbit) -> (Object) -> null
由于构造函数属性在prototype chaing中定义得更深,因此它不是用户对象的自有属性

在您的情况下,名称是在用户对象中定义的属性,但不是在全局对象的上下文中定义的

2以下各项之间有什么区别:

User.constructor;
User.prototype.constructor;
User.constructor;
User.prototype.constructor;
第一个类取用户的构造函数,第二个类取其pro的构造函数 在本例中,键入全局对象

3 User.constructor和 User.prototype.constructor,如果我重写prototype属性,如 这:

请看这个

TL;DR:当你直接访问原型时,你正在打破原型链,创建一个新的原型链。在Rabbit示例中,如果您在某个点执行了以下操作:

Rabbit.prototype = {
   // ...
};
您的新原型链将是:

console.log(User.hasOwnProperty('constructor'));
(Rabbit) -> (Object) -> null
因此,在第一个示例中,User.prototype.constructor将生成:

函数对象{}

在第二个示例中,它将产生:

函数用户名

明白了吗

4用户是功能还是原型还是什么

用户是一个对象,其原型是功能对象,其原型是对象对象

绘制它:

(User) -> (Function) -> (Object) -> null

希望我已经说清楚了。

Javascript与其他语言不同,Java、ecc.不是基于类的,它不提供任何定义类的方法。实际上,下一个Javascript ES6 Harmony引入了class关键字,但它只是原型继承上的一个语法糖,目前在任何浏览器中都不可用

因此,Javascript通过原型继承实现了aka-OOP面向对象编程。 如果要创建自定义对象,则需要使用定义该对象的函数。例如:

var Person=函数{ /** *如果您想使用基于类的语言,那么这就是构造函数 **/ 函数人{} 返回人;
}窗口;如果你要深入研究杂草,重要的是要注意原始布尔、数字和字符串不是对象。它们每个都有对象包装器,但默认情况下它们不是对象。这就是我错过的:“基本上是一个原型…”。但有一点我不明白:console.logUser.prototype;//用户{}//但这应该是对象{}和console.logUser.prototype.constructor;//用户名,但这应该类似于Object,因为上面解释的是父对象。使用您的示例console.log哺乳类动物.prototype可以完美地工作和理解;//Animal{}给出了我期望的结果。User.prototype.constructor是User,至少在Chrome 46中是这样。可能是