首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么是“原型”?

什么是“原型”?
EN

Stack Overflow用户
提问于 2019-10-16 06:12:20
回答 4查看 372关注 0票数 1

我试着把我的头绕在原型上,我很想知道原型到底是什么。很多混淆都是由于不理解用于描述原型的元语言而造成的。

以下是我所知道的:

当我们创建带有属性的命名构造函数时,该构造函数主体内的属性由该构造函数创建的对象实例继承。在这里,我从名为Person的构造函数创建了一个名为person001的实例。

代码语言:javascript
复制
function Person(firstName,lastName) {
    this.firstName = firstName;
    this.lastName = lastName
}
undefined
var person001 = new Person("John","Doe");

当我查看控制台中的对象实例并跟踪原型链时,我发现它位于两个不同的位置。它是dunder对象的构造器对象.

代码语言:javascript
复制
Person {firstName: "John", lastName: "Doe"}
firstName: "John"
lastName: "Doe"
__proto__:
constructor: ƒ Person(firstName,lastName)
__proto__: Object

以及原型对象在同一个构造函数对象中的一个属性。

代码语言:javascript
复制
Person {firstName: "John", lastName: "Doe"}
firstName: "John"
lastName: "Doe"
__proto__:
constructor: ƒ Person(firstName,lastName)
arguments: null
caller: null
length: 2
name: "Person"
prototype: 
constructor: ƒ Person(firstName,lastName)
__proto__: Object
__proto__: ƒ ()
[[FunctionLocation]]: script.js:76
[[Scopes]]: Scopes[1]
__proto__: Object

当我使用命名构造函数的.prototype属性添加属性时,我将该属性添加到prototype对象,而不是构造函数。添加的属性将位于prototype属性的对象中的构造函数旁边。这里,我使用构造函数Person的prototype属性添加了一个名为age的属性。

代码语言:javascript
复制
Person.prototype.age = 0;  

现在我又添加了一个属性,那么原型到底是什么呢?

当我在对象实例person001上运行person001方法时,它会返回我认为类似于原型对象的内容。它有3个属性--一个构造函数、我添加的属性和隐式dunder对象。

代码语言:javascript
复制
Object.getPrototypeOf(person001);
{age: 0, constructor: ƒ}
age: 0
constructor: ƒ Person(firstName,lastName)
__proto__: Object 

那么原型是什么呢?它是原型对象{构造函数,附加属性}吗?还是仅仅是原型对象的构造函数?

提前感谢您的协助。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2019-10-16 08:26:39

当你做obj = new Person时,游戏中有三个玩家:

新创建的对象obj

  • the构造函数Person

  • the prototype,一个存储在Person.prototype

下的特殊隐藏对象

它们之间的关系如下:

代码语言:javascript
复制
obj.__proto__ === Person.prototype

Person.prototype.constructor === Person

说明:

代码语言:javascript
复制
function Person(firstName,lastName) {
    this.firstName = firstName;
    this.lastName = lastName
}

var person1 = new Person("John","Doe");
var person2 = new Person("Ann","Smith");

Person.prototype.age = 42;

票数 2
EN

Stack Overflow用户

发布于 2019-10-16 06:31:23

说您已经为一个人创建了一个构造函数,然后为其创建了两个实例:

代码语言:javascript
复制
const Person = function(name) {
  this.name = name;
  this.speak = () => console.log('My name is ' + this.name)
};
const john = new Person('John');
const mary = new Person('Mary');

john.speak();
mary.speak();

现在,您创建的每个人都有一个不同的名称,他们都可以使用这个名称,因为他们共享来自某个父对象的相同属性。

但玛丽不仅会说话。她会唱歌。但约翰不能。

代码语言:javascript
复制
        const Person = function(name) {
          this.name = name;
          this.speak = () => console.log('My name is ' + this.name)
        };
        const john = new Person('John');
        const mary = new Person('Mary');

        john.speak();
        mary.speak();
        
        mary.sing = () => console.log('♪♪♪ Lalalalalala ♪♪♪');
        
        mary.sing();
        john.sing(); // John is such a bad singer, that this throws an error !

如果你后来意识到你的人不仅需要说话,而且还需要走路,那该怎么办?您需要引用他们的共同父母,以便告诉他们要一条龙地走。这就是原型。Mary和John都有一个共同的原型,并在内心深处引用了该原型(这是__proto__,供朋友和家人使用)。

代码语言:javascript
复制
const Person = function(name) {
      this.name = name;
      this.speak = () => console.log('My name is ' + this.name)
    };
    const john = new Person('John');
    const mary = new Person('Mary');

    john.speak();
    mary.speak();
    
    Person.prototype.walk = () => console.log('I am walking alright');
    
    john.walk();
    mary.walk();
    
    // That is the same as:
    john.__proto__.walk()
    mary.__proto__.walk()

现在约翰摔倒了,走路也有困难。

代码语言:javascript
复制
    const Person = function(name) {
          this.name = name;
          this.speak = () => console.log('My name is ' + this.name)
        };
        const john = new Person('John');
        const mary = new Person('Mary');

        john.speak();
        mary.speak();
        
        Person.prototype.walk = () => console.log('I am walking alright');
        
        // John's infamous accident
        john.walk = () => console.log('My leg hurts so bad...');
        
        john.walk();
        mary.walk();

实例有它自己的属性,我们使用它。

它没有,我们看看它的__proto__,如果它存在的话就使用它。

希望这能有所帮助!

票数 0
EN

Stack Overflow用户

发布于 2019-10-16 06:50:20

首先,原型只是一个对象。JS中的几乎所有对象(除了例如。当您使用Object.create(null))有一些原型和原型可以链接。

示例:当使用文字[]创建数组时,数组实例连接到对象(也是数组实例btw)。定义数组的属性(如map等),它本身连接到另一个原型(对象实例),该原型(对象实例)定义像toString这样的对象的属性。这些属性通常是函数。现在,当您访问像[].hasOwnProperty这样的对象的一个属性时,引擎会查找原型链来查找它。它从您的[]实例开始,没有找到它,继续到原型(数组),也没有成功,所以移到最后一个原型(对象实例),在那里它终于找到了。

正如您所看到的,prototype链总是在某个地方结束,所以如果您试图在链中的最后一个原型上检索原型,您将得到null

现在回到构造函数。首先要注意的是,这些只是正常的函数-实例的实际“创建者”是关键字new。现在,每个函数都有一个prototype属性,它告诉您:使用该函数创建的每个对象都将得到原型--连接到函数的prototype属性中的任何内容。默认情况下,每个函数都在此属性中包含对象实例,这意味着您从该函数创建的每个对象都将是原型--连接到此实例,因此将“继承”类似于toString的属性。

在本例中,您可以看到函数的prototype属性与实例的原型之间的连接。

代码语言:javascript
复制
function A() {}
var a = new A();
a.__proto__ == A.prototype; // is true

最后,函数的constructor属性的prototype属性告诉您,在使用带有new关键字的函数时,将使用哪个函数来创建新实例。这一口可归结为:

代码语言:javascript
复制
function A() {}
A == A.prototype.constructor; // is true

这是对自身的一种引用。在ES6之前创建自己的继承链时,这个属性是可选的,但是为了正确起见还是这样做的。

那么什么是原型呢?它只是一个对象,通过一个特殊的原型连接连接到其他对象实例,使它能够访问预定义的属性。这是在JS中进行继承的一种方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58406799

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档