JS中的面向对象编程之继承机制

一.面向对象编程
面向对象编程(OOP--Object Oriented Programming)是一种抽象方式创建模型的编程方式。继承,封装,多态是OOP的三大基本特征。许多主流编程语言都支持OOP。例如Java,c++中通过new调用‘类’来创造实例,但是学习了JS的同学知道ES6之前中没有类的概念,那么JS怎么实现面向对象编程的呢?
JS实现OOP是通过原型链实现的,原型链的概念在这里不详细讲述,大家记住一个例子即可:

function._proto_ ==== Function.prototype

JS也通过new来创建实例,但是后面调用的不是类,而是构造函数。
下面我们通过封装继承一个‘类’的例子来详细阐述。
二.ES5实现封装 继承一个类
1.封装
我们知道宝马,奔驰,奥迪等都是汽车,汽车这个概念就是一个类,抽象出来代表了日常生活中的许多具体事物。

//汽车 构造函数
function Car (name,color){
this.name = name;
this.color = color;
}

2.prototype模式
汽车的属性有很多,不仅仅是名字和颜色,如果全部写在构造函数里,创建实例时再去一一地调用太过于麻烦,于是JS规定了一个prototype模式,每个构造函数都有一个prototype属性指向原型,“类”里面一些共有的属性可以放在原型里面。例如汽车类的车型,动能方式等属性都是共有属性可以放在原型里。

Car.prototype.type = 'car';

Car.prototype.getType = function () {
  return this.type;
};

Car.prototype.setType = function (newType) {
  this.type = newType;
  return newType;
};

Car.prototype.getName = function () {
  return this.name;
};

Car.prototype.setName = function (newName) {
  this.name = newName;
  return newName;
};

3.new关键字
JS中通过new关键字创建实例。

 var car1 = new Car('宝马','red');
console.log(car1.type) // 'car'

这里,我们思考一个问题:使用new创建实例,new到底做了些什么呢?
使用new创建实例,实际上是帮助我们减少了四行代码:
1.new创建了临时对象,可以使用this访问到临时对象
2.new也帮我们return了这个临时对象
3.new指定了原型的名字--prototype
4.new创建实例,自动绑定原型。

car1._proto_ === Car.prototype

4.继承
我们实现一个‘子类’,继承‘汽车类’

function SUV ( price) {
 Car.call(this, 'suv');   // 将 Car 类的属性和方法赋值给 SUV
  this.price = price;
}
SUV.prototype = new Car('suv');// 继承汽车类的原型链


SUV.prototype.getPrice = function () {
  return this.price;
};
SUV.prototype.setPrice = function (newPrice) {
  this.price = newPrice;
  return newPrice;
};
//创建子类实例
var suv1 = new SUV(1000);
console.log(suv1.getPrice());//1000

三. ES6实现封装继承一个类

1.class封装一个类

ES6中为了让JS与主流面向对象编程语言更相似,引入class(类)的概念,这其实是一个语法糖,本质上,ES6 的类只是 ES5 的构造函数的一层包装,因为class实现的ES5中也能实现。

//类的基本语法
class Car{
constructor(){
}
Car = Car.prototype.constructor
}
var car  = new Car()

class的实质是一个函数,里面默认必须定义一个构造函数,如果不写,默认添加一个空的构造函数。
原型prototype在class上同样也适用,类本身就指向构造函数,使用时也是new一个类实例。
类的写法也可以写成表达式的形式

const BCar = class Car{
    constructor(){
   }
      }
/*注意,在这里BCar才是类的真正名字, Car只能在类内部使用*/

关于this,类中的this默认指向类的实例。

2.继承一个类

ES6中通过extends关键字继承父类。
与es5不同的是,class中不存在变量提升,默认子对象必须在父对象之后定义。

//SUV继承Car类
class Car{
constructor(color,type){
   this.color = color;
   this.type = type;
}
}
class SUV extends Car{
constructor(color,type,price){
  super(color,type){
    this.price =price}}

}

子类也必须拥有一个默认的构造函数
super关键字
子类在构造函数内通过super调用父类的构造函数,否则的话新建子类实例会报错。这也是与ES5不同之处,子类是继承了父类的this对象,然后进行修改。在super内部的this指向的是子类,然而静态方法中的super指向的是父类。
static关键字
与其他语言相似,如果在一个方法前添加static关键字,表示这个一个静态方法,实例不继承该方法,而是需要通过类来调用。同时需要注意,静态方法包含this关键字,这个this指的是类,而不是实例。
类的prototype与proto

class Car{
constructor(color,type){
   this.color = color;
   this.type = type;
}
}
class SUV extends Car{
constructor(color,type,price){
  super(color,type){
    this.price =price}}

}
//////
SUV._proto_ = Car
SUV.prototype._proto_ =  Car.prototype

实例的proto

var car1 = newCar('red', 'fast');
var suv1 = new SUV('red', 'fast', 2018);
/////////
car1._prpto_._prpto_ =  car1._prpto_

3.提供私有方法和私有属性

我们知道C++中的类有私有方法和私有属性,但是ES6中的类没有提供私有方法(仅供类内部使用,外部无法访问)只能变相通过别的方法来提供私有方法和私有属性
--1.私有方法
将私有方法的名字命名为一个Symbol值。

const carO = Symbol('carO');
const carT= Symbol('carT');

export default class Car{

  // 公有方法
  test(car) {
    this[carO](car);
  }

  // 私有方法
  [carO](car) {
    return this[carT] = car;
  }

  // ...
};

--2.私有属性
在属性名之前,使用#表示私有属性

class Car {
  #price;

  constructor(price) {
   this.#price
  }

  get price() { return #price }
  set price(value) { ##price = +value }
}
////price是私有属性,类外部访问不了

以上是JS中的面向对象编程的简单介绍,如有错误,欢迎指出。
参考链接:
Javascript继承机制的设计思想--阮一峰

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,123评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,031评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,723评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,357评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,412评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,760评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,904评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,672评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,118评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,456评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,599评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,264评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,857评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,731评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,956评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,286评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,465评论 2 348

推荐阅读更多精彩内容