彻底搞清楚 JavaScript 的原型和原型链(二)

简介: JavaScript真的挺无语的,怪不得看了那么多的介绍文章还是一头雾水,直到自己终于弄懂了一点点之后才深有体会:先从整体说起吧,发现没有基础做依据,那都是空中楼阁;先从基础开始介绍吧,又发现基础是个蛇头咬蛇尾的圆环,无从下手,应该先整体介绍。于是介绍本身就成了一个死循环。。。

对象 VS 函数

对象和函数的树都画完了,然后我们来分析一下对象和函数的区别。

  • 对象:是一个容器,可以存放各种类型的实例(数据),包括函数。
  • 构造函数:依据原型创建原型的实例。(个人理解可能有误)
  • 一般函数:就是我们“随手”写的函数,执行某些代码,返回结果(也可以不返回)。

从 JavaScript 的语法角度来看,Object、Function、String、Date、Number等都是function,而Object.prototype、String.prototype、Date.prototype、Number.prototype等才是对象。

这和我们经常用到表述方式有点不一样,也正是这个原因,导致理解和表达的时候非常混乱。

我们还是来验证一下:

  • 函数

95.png

对象

96.png


对象的验证.png

这里有一个特例,Function.prototype 是一个函数,而且是所有函数的源头。

所以说,从 JavaScript 的语法角度来看,函数就是函数,对象就是对象,不存在Object既是对象又是函数的情况。

那么到底是什么关系呢?我们定义一套函数来具体分析一下。

实战:用ES6的class定义一套对象/函数

ES6提供了class,但是这个并不是类,而是 Function 的语法糖。目的是简化ES5里面,为了实现继承而采用的各种“神操作”。

用class来定义,结构和关系会非常清晰,再也不会看着头疼了,建议新手可以跳过ES5的实现方式,直接用ES6的方式。

我们先定义一个Base,然后定义一个Person继承Base,再定义一个Man继承Person。也就是说,可以深层继承。

class Base {
constructor (title) {
this.title = '测试一下基类:' + title
}
baseFun1(info) {
console.log('\n这是base的函数一,参数:', info, '\nthis:', this)
}
}
class Person extends Base{
constructor (title, age) {
super(title)
this.title = '人类:' + title
this.age = age
}
personFun1(info) {
console.log('\n这是base的函数一,参数:', info, '\nthis:', this)
}
}
class Man extends Person {
constructor (title, age, date) {
super(title, age)
this.title = '男人:' + title
this.birthday = date
}
manFun3 (msg) {
console.log('jim 的 this ===', this, msg)
}
}

我们打印来看看结构:

97.png

实例的结构.png

  • 构造函数 constructor
    打印结果很清晰的表达了,构造函数就是我们定义的class。

  • 属性
    属性比较简单,统统都挂在 this 上面,而且是同一个级别。

  • 函数
    函数就有点复杂了,首先函数是分级别的,挂在每一级的原型上面。Base的函数(baseFun1),挂在Base的原型上面,_ _ proto__ 指向原型。Person的函数(PersonFun1),应该挂在Person的原型上面,但是打印结果似乎是,Base好像标错了位置。

  • 原型链
    Man的实例 > Man的原型 > Person的原型 > Base 的原型 > Object 的原型。通过 _ _ proto__ 连接了起来。

Man的实例 man1,可以通过这个“链条”,找到 baseFun1,直接用即可(man1.baseFun1()✔), 而不需要使用_ _ proto__(man1.__ proto__.__ proto__.__ proto__.baseFun1()✘)

这个和面对对象的继承是一样的效果。

prototype VS  _ _ proto _ _

看上面两个大树,既有 prototype 又有  _ _ proto _ _,好乱的样子。那么怎么办呢?我们可以找一下规律:

  • prototype:prototype 是自己的原型,可以其原型可以是函数,也可以是对象。有各自的继承体系。
  • __ proto __ :__ proto __ 指向上一级原型,并不是自己的,只是一个指针,方便使用父级的方法和属性。可以指向对象,也可以指向函数。

98.png原型和原型链

组合 VS 继承

一提到面向对象,大家一般都会想到封装、继承、和多态。但是 JavaScript 却不是这个思路。上面那颗大树看起来是继承的关系,Object.prototype 是基类,派生出来 Object.prototype、Function.prototype、string.prototype等。

但是其实这里面隐藏了组合的方式。

我们展开Object 来看看,就会发现自己进入了一个迷宫

99.png


object

object 的“特殊”的结构

看上面的图我们会发现,Object 并不像我们想象的那么简单,有很多的方法,我们随便找几个点开看看:

100.png

object展开三个函数

每一个函数都有自己的原型链(__ proto__),是不是有一种进入迷宫的感觉?我当初看的到时候就被吓退了,这都是个啥?

但是我们换个思路来理解,就清晰多了,那就是:组合代替继承!

Object 其实是由若干个函数组合而成。

其实,想一想,JavaScript 没有私有成员,所以各种细节都暴露出来了,所以我们可以看到原型,看到原型链,看到构造函数。

正是因为看到了这么多的细节,而以前又没有一个比较好的封装方式,所以看起来就特别的乱,理解起来也特别头疼。

总结

按照 JavaScript 的语法来总结,否则总感觉说不清楚。

  • 对象(xxx.prototype)
  • 对象的“根”是 Object.prototype,其上一级是null。
  • 对象只有_ _ proto__,指向上一级原型。
  • 对象没有 prototype,因为Object.prototype、String.prototype、Number.prototype等本身就是对象。通过 _ _ proto__寻找上一级原型。
  • 函数
  • 函数的“根”是 Function.prototype,其上一级是 Object.prototype。
  • 函数有prototype,(JavaScript 语法角度)Object、String、Function、Number 等都是函数,同时也是其原型的构造函数。
  • 函数有_ _ proto__,指向上一级函数。
  • 实例只有_ _ proto__ ,指向函数原型。

本文作者:自然框架

个人网址:jyk.cnblogs.com

声明:本文为 脚本之家专栏作者 投稿,未经允许请勿转载。

相关文章
|
1月前
|
JavaScript 前端开发 开发者
理解JavaScript中的原型链:基础与实践
【10月更文挑战第8天】理解JavaScript中的原型链:基础与实践
|
3月前
|
JavaScript 前端开发
如何在JavaScript中实现基于原型的继承机制
【8月更文挑战第14天】如何在JavaScript中实现基于原型的继承机制
29 0
|
10天前
|
JavaScript 前端开发
JavaScript 原型链的实现原理是什么?
JavaScript 原型链的实现原理是通过构造函数的`prototype`属性、对象的`__proto__`属性以及属性查找机制等相互配合,构建了一个从对象到`Object.prototype`的链式结构,实现了对象之间的继承、属性共享和动态扩展等功能,为 JavaScript 的面向对象编程提供了强大的支持。
|
10天前
|
JavaScript 前端开发
原型链在 JavaScript 中的作用是什么?
原型链是 JavaScript 中实现面向对象编程的重要机制之一,它为代码的组织、复用、扩展和多态性提供了强大的支持,使得 JavaScript 能够以简洁而灵活的方式构建复杂的应用程序。深入理解和熟练运用原型链,对于提升 JavaScript 编程能力和开发高质量的应用具有重要意义。
|
12天前
|
JavaScript 前端开发
如何使用原型链继承实现 JavaScript 继承?
【10月更文挑战第22天】使用原型链继承可以实现JavaScript中的继承关系,但需要注意其共享性、查找效率以及参数传递等问题,根据具体的应用场景合理地选择和使用继承方式,以满足代码的复用性和可维护性要求。
|
22天前
|
JavaScript 前端开发 开发者
探索JavaScript原型链:深入理解与实战应用
【10月更文挑战第21天】探索JavaScript原型链:深入理解与实战应用
28 1
|
30天前
|
JavaScript 前端开发 开发者
深入理解JavaScript原型链:从基础到进阶
【10月更文挑战第13天】深入理解JavaScript原型链:从基础到进阶
22 0
|
30天前
|
JavaScript 前端开发 开发者
原型链深入解析:JavaScript中的核心机制
【10月更文挑战第13天】原型链深入解析:JavaScript中的核心机制
29 0
|
30天前
|
JavaScript 前端开发 安全
深入理解JavaScript原型链:从基础到进阶
【10月更文挑战第13天】深入理解JavaScript原型链:从基础到进阶
27 0
|
2月前
|
JSON JavaScript 前端开发
js原型继承|26
js原型继承|26