手机版

对JavaScript从原型到原型链的深刻理解

时间:2021-08-23 来源:互联网 编辑:宝哥软件园 浏览:

构造函数创建一个对象

让我们首先使用构造函数创建一个对象:

函数Person(){ } var Person=new Person();person.name=' Kevinconsole . log(person . name)//Kevin在这个例子中,person是一个构造函数,我们用new创建了一个实例对象Person。

很简单,让我们言归正传:

原型

每个函数都有一个原型属性,这是我们在各种示例中经常看到的原型,例如:

注释中写了函数Person() {}//但是要注意://prototype是函数所具有的属性。person . prototype . name=' Kevin ';var Person 1=new Person();var Person 2=new Person();console . log(person 1 . name)//kevnoiole . log(person 2 . name)//Kevin这个函数的原型属性到底指向什么?是这个功能的原型吗?

实际上,函数的prototype属性指向一个对象,该对象是通过调用构造函数创建的实例的原型,即本例中person1和person2的原型。

那么原型是什么呢?您可以理解,每个JavaScript对象(除了null)在创建时都会与另一个对象相关联。这个对象就是我们所说的原型,每个对象都将从原型“继承”它的属性。

让我们用一个图表来显示构造函数和实例原型之间的关系:

在这个图中,我们使用Object.prototype来表示实例的原型。

那么我们如何表达实例和实例原型之间的关系,即人和人之间的关系呢?这时,我们就来谈谈第二个属性:

__原型_ _

这是每个JavaScript对象的属性(除了null),称为__proto__,它指向对象的原型。

为了证明这一点,我们可以输入火狐或谷歌:

函数Person(){ } var Person=new Person();console.log(person。_ _ proto _ _===person . prototype);//true因此我们更新了以下关系图:

既然实例对象和构造函数都可以指向原型,那么原型有指向构造函数或实例的属性吗?

构造器

没有实例指向,因为一个构造函数可以生成多个实例,但是原型确实指向构造函数。这是关于第三个属性:构造函数,每个原型都有一个指向关联构造函数的构造函数属性。

为了测试这一点,我们可以尝试:

function Person(){ } console . log(Person===Person . prototype . constructor);//true,因此更新下一个关系图:

综上所述,我们得出结论:

函数Person(){ } var Person=new Person();Console.log (person。_ _ proto _ _==person . prototype)//true console . log(person . prototype . constructor==person)//true//顺便学一个ES5方法。可以得到对象的prototype console . log(object . get prototype of(person)==person . prototype)//true,了解构造函数、实例原型和实例之间的关系。接下来,让我们谈谈实例和原型之间的关系:

示例和原型

当读取一个实例的属性时,如果没有找到,它将在与该对象关联的原型中寻找该属性;如果没有找到,它将寻找原型的原型,直到找到顶层。

例如:

函数Person(){ } Person . prototype . name=' Kevin ';var Person=new Person();人名='黛西';console . log(person . name)//Daisydelete person . name;console . log(person . name)//Kevin在本例中,我们向实例对象person添加了name属性。当我们打印人名时,结果是黛西。

然而,当我们删除人的名字属性时,我们读person.name如果我们不能从person对象中找到名字属性,我们将从person的原型,即person中查找它。__proto__,即Person.prototype幸运的是,我们找到了name属性,结果是Kevin。

但是如果我们还没有找到呢?原型的原型是什么?

原型的原型

前面,我们已经说过原型也是一个对象,既然它是一个对象,我们就可以用最原始的方式创造它,那就是:

var obj=新对象();obj . name=' Kevin ' console . log(obj . name)//Kevin

因此,原型对象由对象构造器生成。结合前面的语句,实例的__proto__指向构造函数的原型,因此我们更新了以下关系图:

原型链

对象的原型呢。原型?

Null,不要相信我们可以打印:

console . log(object . prototype . _ _ proto _ _===null)//true

因此,当您找到属性时,您可以通过找到对象原型来停止搜索.

最后一张图是

顺带一提,图中相关原型组成的链结构就是原型链,也就是蓝线。

补充

最后,补充三点你可能没有注意到的地方:

构造器

第一个是构造函数属性。让我们举个例子:

函数Person(){ } var Person=new Person();console . log(Person . constructor===Person);//true获取person.constructor时,没有person的构造函数属性。如果无法读取构造函数属性,将从person的原型中读取,即Person.prototype,它恰好在原型中具有此属性,因此:

person . constructor===person . prototype . constructor _ _ proto _ _

第二个是__proto__。大多数浏览器支持这种非标准方法来访问原型。然而,它并不存在于Person.prototype中,事实上,它来自Object.prototype,与其说它是一个属性,不如说它是一个getter/setter。使用obj时。__proto__,可以理解为返回object.getprot。

真的是继承吗?

最后,关于继承,我们之前说过“每个对象都会从原型‘继承’属性”。事实上,继承是一个非常令人困惑的说法,引用于《你不知道的JavaScript》:

继承就是复制操作。但是,默认情况下,JavaScript不会复制对象的属性。相反,JavaScript只在两个对象之间创建关联,这样一个对象可以通过委托访问另一个对象的属性和功能。因此,委托比继承更准确。

以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。

版权声明:对JavaScript从原型到原型链的深刻理解是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。