• 首页
  • 技术
  • 旅行
  • 车模
  • 关于

JZ's Blog

{技术, 绘画, 旅行, 摄影, 多肉}
  • 首页
  • 技术
  • 旅行
  • 车模
  • 关于
首页  /  技术  /  图解JavaScript原型继承
15 九月 2017

图解JavaScript原型继承

作者:jz1108
技术 写评论

怎么又忽然想起写JavaScript原型继承这个基础的内容。最近在写一个小程序,要从底层实现继承,突然发现我对这么基础知识的记忆模糊起来。于是迅速找文章来读,才又重新拾起,现在想把相关的内容通过图形化的方式记录在自己的博客上,保不齐过一段时间我又忘了呢。

构造函数

在JavaScript中,一个普通的函数即可充当构造函数:

function Car() {

}

上例中 Car 是一个函数的实例,它有一个prototype属性,可以在该属性上添加方法:

Car.prototype.move = function () {

};

通过 new 关键字即可创建一个 Car 的实例:

var myCar = new Car();

并且可以调用 move 方法:

myCar.move();

我们都知道 move 方法并不是位于 myCar 这个对象上,而是在 myCar 对象的原型链上。myCar 对象有个 __proto__ 属性,该属性指向 Car.prototype。当调用 myCar.move() 时,JavaScript 引擎首先看方法是否存在于 myCar 对象,如果不存在则再看是否存在于 myCar.__proto__ 上,由于 myCar.__proto__ 与 Car.prototype 指向同一个对象,由此便可以调用到 move() 方法。下面的图描述了这样的关系:

在 JavaScript 中,还有一个 instanceof 操作符,通过它可以知道某个对象是否是某个构造函数的实例:

myCar instanceof Car; // true

当调用 instanceof 操作符时,JavaScript 引擎会判断 myCar 的 __proto__ 是否与 Car.prototype 指向同一个对象,如果是则返回 true。

原型继承

接下来我们看如何通过原型的方式实现面向对象的继承:

function Sedan() {
    Car.call(this);
}

插入解释一下什么是 Sedan:

A sedan is a car with seats for four or more people, a fixed roof, and a boot that is separate from the part of the car that you sit in.

在 Sedan 构造函数中,通过 Car.call(this) 实现了在子类的构造函数中调用父类构造函数的方法。接下来我们修改 Sedan.prototype 对象为一个 Car 的实例:

Sedan.prototype = new Car();

接下来可以实例化一个 Sedan 对象,并调用 move 方法:

var mySedan = new Sedan();
mySedan.move();

下图描述了继承关系:

Car.prototype 对象还有一个 constructor 属性,它指向 Car 本身:

Car.prototype.constructor === Car; // true

显然在第一个例子中,下面的结果是 true:

myCar.constructor === Car; // true

通过原型链(__proto__ 属性),访问 myCar.constructor 的时候实际上就是访问了原型对象的 constructor 属性,也就是 Car.prototype.constructor。

但是你会发现 mySedan 的 constructor 也成为 Car 了。显然是因为 mySedan 原型链被修改到了 Car 的实例上,顺着原型链就会最终访问 Car.prototype.constructor。因此在实际使用中,要把修改的 constructor 改回来:

var originalConstructor = Sedan.prototype.constructor;
Sedan.prototype = new Car();
Sedan.prototype.constructor = originalConstructor;

最终的关系图如下所示:

 Previous Article 利用 WebGL 实现 VR
Next Article   泰国行——大皇宫及周边

相关文章

  • iOS 13 Safari 的一些变化

    2019年11月13日
  • WebGL 文章汇总

    2019年9月12日
  • 高性能 WebGL —— 使用 ImageBitmap 提升纹理性能

    2019年3月24日

留言

取消回复

近期文章

  • iOS 13 Safari 的一些变化
  • WebGL 文章汇总
  • 高性能 WebGL —— 使用 ImageBitmap 提升纹理性能
  • 跨越1600公里的旅行——车专辑
  • 跨越1600公里的旅行——大洋路

近期评论

  • jz1108发表在《WebGL绘制详解之七:Blend》
  • jz1108发表在《高性能WebGL——使用顶点数组对象 Vertex Array Object》
  • jz1108发表在《德国之行——新天鹅堡和小镇菲森》
  • 朱发表在《高性能WebGL——使用顶点数组对象 Vertex Array Object》
  • granx18发表在《WebGL 文章汇总》

文章归档

  • 2019年十一月
  • 2019年九月
  • 2019年三月
  • 2018年十二月
  • 2018年十一月
  • 2018年十月
  • 2017年十一月
  • 2017年十月
  • 2017年九月
  • 2017年五月
  • 2017年四月
  • 2017年三月
  • 2017年二月
  • 2017年一月
  • 2016年十一月
  • 2016年十月
  • 2016年四月
  • 2016年三月
  • 2016年二月
  • 2016年一月
  • 2015年十二月
  • 2015年十一月
  • 2015年十月
  • 2015年九月
  • 2015年八月
  • 2015年七月
  • 2015年六月
  • 2015年三月
  • 2014年十二月
  • 2014年十一月
  • 2014年十月
  • 2014年八月
  • 2014年七月
  • 2014年六月
  • 2014年五月
  • 2014年四月
  • 2014年三月
  • 2014年二月
  • 2014年一月
  • 2013年十二月
  • 2013年十一月
  • 2013年十月
  • 2013年九月
  • 2013年八月
  • 2013年七月
  • 2013年六月
  • 2013年五月
  • 2013年四月
  • 2013年三月
  • 2013年二月
  • 2013年一月
  • 2012年十二月
  • 2012年十月
  • 2012年九月
  • 2012年七月
  • 2012年六月
  • 2012年五月
  • 2012年一月
  • 2011年十一月
  • 2011年十月
  • 2011年九月
  • 2011年八月
  • 2011年七月
  • 2011年六月
  • 2011年五月
  • 2011年四月
  • 2011年二月
  • 2011年一月
  • 2010年十二月
  • 2010年十月
  • 2010年九月
  • 2010年六月
  • 2010年五月
  • 2010年四月
  • 2010年三月
  • 2010年二月
  • 2010年一月
  • 2009年十二月
  • 2009年十一月
  • 2009年九月
  • 2009年八月
  • 2009年六月
  • 2009年三月
  • 2009年二月
  • 2009年一月

分类目录

  • 地图API
  • 多肉
  • 开发
  • 技术
  • 摄影
  • 旅行
  • 未分类
  • 汽车
  • 绘画
  • 美食
  • 车模
  • 随笔

功能

  • 登录
  • 文章RSS
  • 评论RSS
  • WordPress.org
© Copyright 2015. Theme by BloomPixel.