一文搞懂JavaScript原型及原型链(附代码)

boyanx2个月前技术教程15

JavaScript 是一种基于原型的面向对象语言。虽然你经常会看到class关键字,但它的底层本质还是用作原型。

在本文中,我们将了解 JavaScript 的原型性质,以及对象中的原型链。

首先检查以下代码:

const animals = {

name: "animal",

type: "object",

}

animals.hasOwnProperty("name")// true

但是我们并没有给animals定义方法hasOwnProperty,可它为什么可以调用该方法?在本文结束时,我们将了解其工作原理以及更多内容。

一、原型的概念

根据查阅得到的字面意思的解释是:

指一个词语或一个类型意义的所有典型模型或原形象,是一个类型的典型特征,我们可以用下图中的车辆示例很好地解释这一点。

原型“A”是创建其他版本(如“B”和“C”)的第一个版本。“A”包含车辆应具备的最基本功能,而“B”和“C”将包含更多的功能。

这意味着,“B”和“C”是“A”的改进版本,但仍包含“A”的特征。“A”有四个轮胎,“B”也有四个轮胎,但是可以飞,“C”同样有四个轮胎,但是可以在水上行驶。

JavaScript 在原型的基础上工作。在每个函数的声明中,JavaScript 引擎将prototype属性添加到该函数,这使该函数成为可以创建其他版本的原型。我们可以通过打印其属性确认:

function hello() {

console.log("hello")

}

console.dir(hello)

结果:

如上图所示,显示了函数的属性,hello函数中包括了prototype属性, 以及另一个名为__proto__的属性。本文稍后会详细介绍。

该prototype对象有两个属性:一个名为constructor以及另一个同样名为__proto__的属性。前者指向hello函数,后者指向Object。

二、原型的好处

说原型的好处之前我们先说一下构造函数,这是创建对象的一种方式,如下所示:

function Hello() {

console.log("hello")

}

const anotherVersion = new Hello()

anotherVersion.type = "new"

console.log(anotherVersion)

Hello首字母大写是一种约定,表示该函数可以用作构造对象,这个函数也被称为构造函数。

结果:

结果现在向我们展示了这个anotherVersion对象是一个从Hello函数通过new关键字而变化来的。你可以通过这种方式去创建类似具有相同功能的对象,例如:

function Obj(name) {

this.name = name;

this.printName = function () {

console.log(this.name)

}

}

const javascript = new Obj("javascript")

const java = new Obj("java")

console.log(javascript)// Obj {name: 'javascript', printName: f}

console.log(java)// Obj {name: 'java', printName: f}

构造函数中的this变量指向构造函数new出来的实例化对象(在上面的代码中是javascript和java)。

我们可以看到,虽然javascript和java具有不同的名称值,但它们具有相同的功能代码。

使用原型的好处就是,你可以通过一个构造函数去创建很多具有相同功能的对象,并且这些对象都具有不同的名字。

还记得上面hello函数有两个属性:prototype和__proto__。prototype还有两个属性:constructor和__proto__。使用构造函数创建对象时,使用了prototype属性的constructor属性,让我们用下面的代码检查一下:

function Obj(name) {

this.name = name

this.printName = function () {

console.log(this.name)

}

}

const javascript = new Obj("javascript")

console.log(javascript)

结果:

从上图中,你会看到__proto__属性连接到我们的构造函数Obj。

三、与原型共享功能

现在我们知道函数的prototype属性使该函数成为可用于创建其他对象的原型。

如果该prototype属性有其他属性呢?我们知道,JavaScript 对象可以在任何时候添加新的属性,让我们来看看:

function Obj(name) {

this.name = name

this.printName = function () {

console.log(this.name)

}

}

const javascript = new Obj("javascript")

Obj.prototype.printType = function () {

console.log(this.type)

}

console.log(javascript)

结果:

如上图所示,__proto__属性现在有一个printType方法,但对象javascript本身没有printType方法。由上面所述结果我们可以知道,__proto__属性连接我们的构造函数,由于javascript在默认情况下可以访问__proto__属性中的构造函数,因此它也可以访问printType。因此,以下操作将正常工作:

javascript.printType()// undefined

javascript.type = "language"

javascript.printType()// language

JavaScript 是如何做到这一点的呢?首先它检查对象是否存在该方法,如果不存在,它检查__proto__属性。

四、原型链

我们看最后一张图片,你会注意到车辆B和C也有自己的原型,这意味着Obj用作原型的对象也继承了另一个原型的一些特性,这称为原型链。

这说明,一个对象可以是原型的新版本,同时也是另一个对象的原型。因此,当你尝试访问对象上的属性时,JavaScript引擎开始从对象自身中查找该属性,如果没有,它会继续检查__proto__,一直到没有__proto__或者找到该属性。如果找到最后,此属性不存在时,返回undefined

五、总 结

回到第一个代码块:

const animals = {

name: "animal",

type: "object",

}

animals.hasOwnProperty("name")// true

到现在你应该清楚了,对吧?

当你的animals在控制台打印的时候,您会注意到它有一个__proto__指向Object的原型。并且,Object的原型具有hasOwnProperty属性。animals继承了该属性,这使得它可以使用该属性。

Object在 JavaScript 中有一个所有对象都能继承的原型。Function、String等构造函数也从Object继承了属性。

这也就是为什么string.toLowerCase()也可以直接使用的原因。构造函数的原型对象String具有所有这些属性,因此字符串可以使用它们。

相关文章

《深入理解javascript原型和闭包系列》 知识点整理

深入理解javascript原型和闭包系列对原型和闭包等相关知识的讲解,由浅入深,通俗易懂,每个字都值得细细研究。一、一切都是对象1. typeof操作符输出6种类型:string boolean n...

什么是 ASCII 码?常见的 ASCII 码表(十进制、十六进制、字符对照)

在今天的计算机世界里,我们随时都在与“字符编码”打交道。写代码、发消息、传文件……背后都有一套规则在运作。而这一切的起点,正是 ASCII 码(American Standard Code for I...

使用函数化的Javascript代码编写方式

对于Javascript介绍想必大家都耳熟能详啦, 基于函数化的编程语言, 基于浏览器运行的编程语言, web开发语言, 前端开发必备语言, blablabla... Javascript是一个非常灵...

超实用的一行 TypeScript 工具函数,写代码必备!

前言在日常开发中,我们经常会遇到一些「小需求」:比如要打乱数组、随机生成字符串、延迟一会儿执行代码…… 这些需求看似简单,却总是要「现写一遍」,久而久之就很浪费时间下面整理了一份 一行就能搞定的 Ty...

在交互设计的过程中如何做到为用户节省时间

用户的时间也是宝贵的,我们不能让它白白浪费掉!在每个项目中我们都要问自己两个问题:“我们为用户节省时间了吗? ”、“我们是如何为用户节省时间的?“在社会中什么东西是最宝贵的? 金钱? 地位? 我认为是...

Python/JS/GO/JAVA四语言同步学(第十四章_字符串字母大小写转换)

全网首发!(第十四章)PY/JS/GO/JAVA四语言字符串大小写转换参数宇宙(200例源码/同步学习/避坑指南)知识一锅端|打通任督二脉 多语言逆袭指南 单语言学习是伪命题!真正的高手早用「四语言...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。