js之class的前世今生

Javascript之class的前世今生

最早JavaScript中所谓的类,其实是一种设计模式:一个构造函数(consturctor)和一个用于在该类实例间共享属性和方法的原型对象(Objcet.prototype)的结合。为了达到继承,通过函数来模拟类来创建对象。

今天我主要讲讲js类的发展,一是理清class的实质,二是掌握继承extends的实现,三是梳理ES6以前的关于这方面的知识。

ES6 class的前世

(1)创建对象

js引入class的目的,其实就是为了创建对象,这里梳理一下ES6以前创建对象的方式。

一、最基础的new
var friend = new object();
friend .name = "girl";
friend .speak = function(){
	console.log(this.name + "_said:I miss you");
}
二、字面向量
var friend = {
	name: 'girl',
	speak: function(){
		console.log(this.name + "_said:I miss you");
	}
};

方法一、二虽然可以创建对象,但是不易封装复用

三、工厂模式
function friend(name){
  var o = new object();
  o.name = name;
  o.speak = function(){
	console.log(this.name + "_said:I miss you");
  }
  return o;
}

var somebody = new friend("girl");
somebody.speak();

比起一二,friend函数确实是封装了一个属性和一个方法。然而有个问题,这个函数无法解决对象识别问题,就是创造出来的实例如somebody是Object类型,因为o是从Object里new出来的。

四、构造函数
function friend(name){
  this.name = name;
  this.speak = fucntion(){
	console.log(this.name + "_said:I miss you");
  }
}
var somebody = new friend("girl");
somebody.speak();

虽然这个方法解决了三的问题,但还是有缺陷。每次创建friend对象,每个对象都会有一个speak方法,消耗很大。

五、原型封装
function friend(name){
  this.name = name;
}
friend.prototype.speak = function(){
  console.log(this.name + "_said:I miss you");
}

var somebody = new friend("girl");
somebody.speak();

和构造函数不同的,这里通过原型封装的新对象的方法是所有实例都可以共享的。

(2)继承

现在已经能完成创建对象的要求了,但是类还有继承的要求。

六、基于原型链的继承

在这里插入图片描述

基于原型链的特点,通过将子类构造函数的原型作为父类构造函数的实例,这样就连通了子类-子类原型-父类原型,原型链的特点就是逐层查找,从子类开始一直往上直到所有对象的原型Object.prototype,找到属性方法之后就会停止查找,所以下层的属性方法会覆盖上层。

方法一:

function friend(name){
  this.name = name;
}

function girlFriend(name){}

girlFriend.prototype = new friend(name);
girlFriend.prototype.constructor = girlFriend;

var a = new girlFriend("L");
console.log(a.name);	//L

1.把子类girlFriend的原型对象指向父类的实例化对象,这样即可以继承父类friend原型对象上的属性和方法
2.这时子类的constructor属性会指向friend,手动把constructor属性指向子类girlFriend,就可以在父类的基础上添加属性和方法了

方法二:

function friend(name){
  this.name = name;
}

function girlFriend(name){
  friend.call(this,name);
}

var a = new girlFriend("L");
console.log(a.name);	//L

ES6 class的今生

在这里插入图片描述

class friend{
	constructor(name) {
		this.name = name; 
	}

	speak() {
		console.log(this.name + "_said:I miss you");
	}
}

class girlFriend extends friend {
	constructor(name) {		
		super(name);		//如果子类中存在构造函数,则需要在使用“this”之前首先调用super()
		this.name = name;
	}

	speak() {
		super.speak();	
	}
}

1.子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。
2.直接调用super(name),就可以直接继承父类的属性和方法

可对比ES5的两种继承方法理解代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值