优选 | 疯狂拉扯 javascript 中的原型链

2,808 阅读5分钟

哈喽,大家好!我是陈坚强。一个有代码洁癖的前端攻城狮( 哈哈,生活很邋遢(* ̄︶ ̄) )

javascript有两大链条,一条是作用域链,一条是原型链

今天我们来开始撸一撸javascript的这条原型链(想和坚强聊聊作用域链的Baby,可以关注来一波哈, —————— 爱你的坚强)

OK、正文开始~~

概念解释

javascript是一种面向对象的、解释型弱语言,那下面我们先弄清楚这几个概念

  • 函数(function)
  • 函数对象(function object)
  • 本地对象(native object)
  • 内置对象(build-in object)
  • 宿主对象(host object)

函数

前者为函数声明,后者为函数字面量,typeof person/person1的结果都是 function

函数对象

函数就是对象,代表函数的对象就是函数对象 上面,我们所建立的对象,就是函数对象

本地对象

ECMA-262 把本地对象(native object)定义为“独立于宿主环境的 ECMAScript 实现提供的对象”。简单来说,本地对象就是 ECMA-262 定义的类(引用类型)。它们包括: Object,Function,Array,String,Boolean,Number Date,RegExp,Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError.

我们不能被他们起的名字是本地对象,就把他们理解成对象(虽然是事实上,它就是一个对象,因为JS中万物皆为对象),通过typeof 返回的结果都是function

也就是说其实这些本地对象(类)是通过function建立起来的 可以看出Object原本就是一个函数,通过new Object()之后实例化后,创建对象。

内置对象

ECMA-262 把内置对象(built-in object)定义为“由 ECMAScript 实现提供的、独立于宿主环境的所有对象,在 ECMAScript 程序开始执行时出现”。这意味着开发者不必明确实例化内置对象,它已被实例化了。ECMA-262 只定义了两个内置对象,即 Global 和 Math (它们也是本地对象,根据定义,每个内置对象都是本地对象)。

理清楚了这几个概念,有助于理解我们下面要讲述的原型和原型链。

什么是原型

想知道原型,我们先来搞明白三个关键字,哦不,是关键词!

  1. _proto_
  2. prototype
  3. constructor

_proto_、 prototype

任何对象都有一个原型对象,这个原型对象由对象的内置属性__proto__指向它的构造函数的prototype指向的对象,即任何对象都是由一个构造函数创建的,但是不是每一个对象都有prototype,只有方法才有prototype

constructor

function声明的都是函数,而如果直接调用的话,那么Person()就是一个普通函数,只有用函数new产生对象时,这个函数才是new出来对象的构造函数。(看完这几个关键词有点晕了?是不是很绕?那先上个图看看 -_-!)

  • 小伙伴:坚强,还是晕
  • 坚强:国内著名画家,陈坚强上线(黑一波MAC自带画图工具,em.....)

创建对象的过程

知道什么是原型了,那么我们来聊一聊创建对象的过程

声明构造方法(类)

为啥在构造方法后面加个类呢,是因为类即class也可以创建对象

ES5   =>   构造方法         ES6   =>   类class

Tip:通常构造函数和类的命名使用大驼峰

new一个对象

没有对象?不怕!new一个不就完事了,让我们来看一下他们之间的关系

我们可以的发现,new出来的对象,它的constructor指向了Person

new一个对象,它的__proto__属性指向了方法的prototype属性,并且constructor指向了prototypeconstructor属性。

new到底干了什么

  1. 创建一个空对象
  2. 设置这个新的对象的内部、可访问性和[[prototype]]属性为构造函数(指prototype.construtor所指向的构造函数)中设置的;
  3. 执行构造函数,当this关键字被提及的时候,使用新创建的对象的属性; 返回新创建的对象(除非构造方法中返回的是‘无原型’)。
  4. 在创建新对象成功之后,如果调用一个新对象没有的属性的时候,JavaScript 会延原型链向止逐层查找对应的内容。这类似于传统的‘类继承’。

Tip: 在第二点中所说的有关[[prototype]]属性,只有在一个对象被创建的时候起作用,比如使用new关键字、使用 Object.create 、基于字面意义的(函数默认为 Function.prototype ,数字默认为 Number.prototype 等)。它只能被Object.getPrototypeOf(someObject) 所读取。没有其他任何方式来设置或读取这个值。送上权威文档的飞机票

原型链

上面讲了那么多就是为下面做铺垫,嘻嘻

什么是原型链?

原型链的核心就是依赖对象的__proto__的指向,当自身不存在的属性时,就一层层的扒出创建对象的构造函数,直至到Object时,就没有__proto__指向了。

原型链的简单实践

多级原型链接成为了原型链

原型链的作用

  • 实例对象可以使用原型链上对象的方法或者属性
  • 查找顺序:从自身往上查找(先到先得)

重写原型链上的方法

原型链图解

这是小编在网上找的图,感觉挺不错的,就推荐给大家

结束语

相信看完这篇文章,你对javascript原型链有了新的理解和认识,不要忘了给小编关注,点赞哦