理解javascript中的class

转载自https://segmentfault.com/a/1190000008338987

在 ES6 规范中,引入了 class 的概念。使得 JS 开发者终于告别了,直接使用原型对象模仿面向对象中的类和类继承时代。

但是JS 中并没有一个真正的 class 原始类型, class 仅仅只是对原型对象运用语法糖。所以,只有理解如何使用原型对象实现类和类继承,才能真正地用好 class

通过类来创建对象,使得开发者不必写重复的代码,以达到代码复用的目的。它基于的逻辑是,两个或多个对象的结构功能类似,可以抽象出一个模板,依照模板复制出多个相似的对象。就像自行车制造商一遍一遍地复用相同的蓝图来制造大量的自行车

使用 ES6 中的 class 声明一个类,是非常简单的事。它的语法如下:

class Person {
	constructor(name){
		this.name = name;
	}
	hello() {
		console.log('hello, my name is '+ this.name + '.');
	}
}
var xiaoMing = new Person('xiaoMing');
xiaoMing.hello(); // hello, my name is xiaoMing

xiaoMing是通过类Person实例化出来的对象。对象xiaoMing是按照Person这个模板,实例化出来的对象。实例化出来的对象拥有预先定制好的结构和功能。

class实例化的背后原理

使用 class 的语法,让开发者告别了使用 prototype 模仿面向对象的时代。但是,class 并不是 ES6 引入的全新概念,它的原理依旧是原型继承。

通过类型判断,class并不是什么全新的数据类型,实际只是function

使用es5创建一个类,并将它实例化,来看看本质

function Person(name) {
	this.name = name
}
// 首先给 Person.prototype 原型对象添加了 describe 方法
Person.prototype.describe = function() {
	console.log('hello,my name is ' + this.name + '.');
}
// 实例化对象的 __proto__ 指向 Person.prototype
var jane = new Person('jane');
jane.__proto__ === Person.prototype;
// 读取 describe 方法时,实际会沿着原型链查找到 Person.prototype 原型对象上
jane.describe() // hello, my name is jane.

上述使用 JS 模仿面向对象实例化的背后,实际有三个步骤:

  1. 首先给 Person.prototype 属性所指的原型对象上添加了一个方法 describe。
  2. 在使用 new 关键字创建对象时,会默认给该对象添加一个原型属性 __proto__,该属性指向 Person.prototype 原型对象。
  3. 在读取 describe 方法时,首先会在 jane 对象查找该方法,但是 jane 对象并不直接拥有 describe 方法。所以会沿着原型链查找到 Person.prototype 原型对象上,最后返回该原型对象的 describe 方法

class定义属性

当我们使用class定义属性的时候,实际上等于是在class的原型对象上定义属性。

class Foo{
	constructor(){
		/* constructor */
	}
	describe(){
		/* describe */
	}
}
// 等价于
function Foo() {
	/* constructor */
}
Foo.prototype.describe = function(){/* describe */}

类继承:

在传统面向对象中,类是可以继承类的。这样子类就可以复制父类的方法,达到代码复用的目的

ES6 也提供了类继承的语法 extends,如下:

class Foo {
	constructor(who){
		this.me = who;
	}
	identify(){
		return 'I am' + this.me;
	}
}

class Bar extends Foo {
	constructor(who) {
		super(who);
	}
	speak(){
		alert('hello,' + this.identify() + '.');
	}
}
var b1 = new Bar("b1");
b1.speak();

当实例 b1 调用 speak 方法时,b1 本身没有 speak,所以会到 Bar.prototype 原型对象上查找,并且调用原型对象上的 speak方法。调用 identify f时,由于 this 指向的是 b1 对象。所以也会先在 b1 本身查找,然后沿着原型链,查找 Bar.prototype,最后在 Foo.prototype 原型对象上找到 identify 方法,然后调用。

super关键字用于访问和调用一个对象的父对象上的函数

子类在访问使用his前必须先在constructor方法里调用super方法,否则新建实例时会报错。

这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值