好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

ES6+ Class

ES6+ Class

1. 前言

上一节我们主要回顾了在 ES5 中使用构造 函数 的方式实现类了,并说明了如何实现类的继承。从上一节的讲解中,构造 函数 去实现类的继承还是有诸多繁琐的地方的,我们需要考虑子类和 父类 的关系,继承中的细节都需要自己手动处理。本节我们将要学习 ES6 中的类的基本使用和类的继承。在学习本节我们需要明确的是,ES6 中的类是基于现有语法的原型实现的,并没有引入新的面相对象的模型。它的本质还是我们上节提到的构造 函数 ,只是让我们更加方便地使用,是基于原型的继承的语法糖。

2. 基本 用法

2.1 语法

上节我们在实现类的时候说,类不能被执行只能 new 来创建实例,当时我们是在内部手动处理的。在 ES6 中天然 支持 这个特性:

  class   Animal   {   } 
 Animal  (  )  ; 
 // Uncaught TypeError: Class constructor Animal cannot be invoked without 'new' 
 

上面的 代码 中我们定义了 一个 动物类,在控制台中让其执行,会看到如上的未捕获的类型 错误 :意思是在没有 new 的情况下是无法 调用 构造 函数 Animal 的。使用 class 定义的类和使用构造 函数 定义类,在使用上是一样的,只是创建类的方式不一样。

上节我们知道如何创建实例上的 属性 和原型上的 属性 ,那么使用 class 是怎么实现的呢?class 类提供了 constructor 方法 ,并在 new 的时候 默 认执行,所以在 constructor 函数 内部在 this 上绑定实例上的 属性 。而 原型上的 方法 则是在对象中直接 添加 属性 即可,实例如下:

  class   Animal   { 
   constructor  (  )   { 
     this  . type  =   '鸟类' 
   } 
   eat  (  )   {  } 
 } 
 var  a  =   new   Animal  (  )  ; 
console .  log  ( a .  hasOwnProperty  (  'type'  )  )  ; 	 // true 
console .  log  ( a .  hasOwnProperty  (  'eat'  )  )  ; 		 // false 
 

另外,在 ES7 中 class 还提供了一种方式在实例上绑定 属性 ,这种方式不需要 this,直接使用等号在 class 类中进行赋值。

  class   Animal   { 
   constructor  (  )   { 
     this  . type  =   '鸟类' 
   } 
  age =  '100' 
   eat  (  )   {  } 
 } 
 var  a  =   new   Animal  (  )  ; 
console .  log  ( a .  hasOwnProperty  (  'age'  )  )  ; 	 // true 
 

需要注意的是,上面的等号赋值方式要在 支持 ES7 的环境中才能执行。

2.2 get/set

当我们深入了解对象时我们就会知道 属性 的 getter 和 setter ,提供了 get 和 set 两个 方法 用于访问和设置 属性 。在 ES5 中有 Object.define property() 方法 可以对对象的 属性 进行劫持,Vue2 的底层就是使用这个 API 实现的。当然 class 类其实也是 一个 对象,它也可以使用 get 的方式返回 属性 值。如下实例:

  class   Animal   { 
   constructor  (  )   { 
     this  . type  =   "鸟类"  ; 
     this  . _age  =   ; 
   } 
   get   a  (  )   { 
     return   this  . _age ; 
   } 

   set   a  ( newValue )   { 
     this  . _age  =  newValue ; 
   } 
 } 

 var  animal  =   new   Animal  (  )  ; 
console .  log  ( animal . a )  ;   // 8 
animal . a  =   ; 
console .  log  ( animal . a )  ;   // 10 
 

上面 代码 中我们就使用了 get 和 set 去 获取 属性 值和设置 属性 值。那我们思考 一个 问题,set 和 get 是自有 属性 还是原型上的 属性 呢?其实 get 和 set 还是 class 类上的 一个 方法 ,所以是原型上的 方法 。

 console .  log  ( a .  hasOwnProperty  (  'a'  )  )  ; 	 // false 
 

@H_224_ 419 @2.3 static

ES6 提供了用于定义静态 属性 和 方法 的关键字 static ,静态 方法 调用 时不需要实例化该类,所以就不能通过实例去 调用 ,但可以使用类直接去 调用 。

静态 方法 通常用于为 一个 应用程序创建工具 函数 ,下面我们来看 一个 长方形类,定义 一个 获取 长方形面积的静态 方法 。

  class   Rectangle   { 
   constructor  ( width ,  height )   { 
     this  . width  =  width ; 
     this  . height  =  height ; 
   } 

   static   getArea  ( r )   { 
     return  r . width  *  r . height ; 
   } 
 } 

 const  r  =   new   Rectangle  (  ,   )  ; 

console .  log  ( Rectangle .  getArea  ( r )  )  ; 	 // 50 
 

3. 继承

3.1 extends

在上节构造 函数 中的继承我们知道,子类的构造 函数 中,需要我们去手动执行父构造 函数 并绑定this,还需要将子类的构造 函数 的原型链执行 父类 的原型。ES6 中的继承非常简单,在创建子类时只需要使用关键字 extends 即可创建 一个 子类。

  //  父类 :动物 
 class   Animal   { 
   constructor  ( name )   { 
     this  . name  =  name ; 
   } 
   eat  (  )   { 
    console .  log  (  this  . name  +   '会吃饭!'  )  ; 
   } 
   static   getAge  (  )   { 
		console .  log  (  ' 获取 '   +   this  . name  +   '的年龄10岁了'  )  ; 
		 return   ; 
   } 
 } 

 // 子类:具体的动物——狗 
 class   Dog   extends   Animal   {  } 
 

上面的 代码 中子类 Owl 继承了 Animal,那这个时候我们都继承了什么呢?从上面的学习中 父类 中有,this 上的 属性 ,原型上的 方法 和静态 方法 。

  var  dog  =   new   Dog  (  '狗'  )  ; 

console .  log  (  'name:'  ,  dog . name )  ; 			 // name: 狗 
console .  log  (  'age:'  ,  Dog .  getAge  (  )  )  ; 	 // age: 10 
dog .  eat  (  )  ; 	 // 狗会吃饭! 
 

从上面 代码 打印的结果,我们知道,实例 dog 已经继承了 Animal 上的 属性 和 方法 。在 父类 中对 eat 方法 的定义不明确,所以在子类中我们重写 eat 方法 。

  class   Dog   extends   Animal   { 
   eat  (  )   { 
    console .  log  (  this  . name  +   '会吃饭!'  )  ; 
   } 
 } 
 var  dog  =   new   Dog  (  '狗'  )  ; 
dog .  eat  (  )  ; 	 // 狗喜欢吃骨头! 
 

3.2 super

super 是 class 中的关键字,可以理解是 父类 的别名,用于 调用 对象的父对象上的 函数 。一般 super 有两种情况: super 当做 函数 调用 ;一种是 super 当做 父类 的对象使用。

第一种情况下, super 关键字作为 函数 调用 ,它的作用是为了绑定 this。所以子类的构造 函数 必须执行一次 super。 默 认情况下,类中不写 constructor 时,constructor 会 自动 执行 super, 并绑定 this 指向当前子类。

  class   A   {  } 

 class   B   extends   A   { 
   constructor  (  )   { 
     super  (  )  ; 
   } 
 } 
 

上节中我们在创建子类时就去执行了 父类 并绑定了this,上面 代码 中的 super 和 A.call(this) 是相同的。

第二种情况下,super 当作 父类 的对象来使用的,什么情况下会使用呢?当我们在子类中想使用 父类 的 方法 时可以使用 super 直接 调用 父类 的 方法 即可。

  class   A   { 
   getCount  (  )   { 
     return   ; 
   } 
 } 

 class   B   extends   A   { 
   constructor  (  )   { 
     super  (  )  ; 
    console .  log  (  super  .  getCount  (  )  )  ;   // 7 
   } 
 } 

 let  b  =   new   B  (  )  ; 
 

4. 小结

本节主要学习了 ES6 中 class 类的使用和相关的知识点,需要明确的是 class 类就是 一个 语法糖,底层还是基于现有的原型对象的继承来实现的。所以要想深入理解 ES6 的 class 就需要对 ES5 中的构造 函数 有深入的理解,另外,我们可以使用 babel 进行转译,得到的 代码 就是使用构造 函数 来实现的。

查看更多关于ES6+ Class的详细内容...

  阅读:43次

上一篇

下一篇

第1节:ES6+ 简介    第2节:ES6 环境配置    第3节:ES6+ let    第4节:ES6+ const    第5节:ES6+ 展开语法    第6节:ES6+ 剩余参数    第7节:ES6+ 解构赋值    第8节:ES6+ 模版字符串    第9节:ES6+ 箭头函数    第10节:ES6+ 数值扩展    第11节:ES6+ isFinite()&isNaN()    第12节:ES6+ Number 对象的方法    第13节:ES6+ Math 对象的扩展    第14节:ES6+ includes()    第15节:ES6+ 字符串的扩展    第16节:ES6+ startsWith()    第17节:ES6+ endsWith()    第18节:ES6+ repeat()    第19节:ES6+ padStart()    第20节:ES6+ padEnd()    第21节:ES6+ trim()    第22节:ES6+ Array.from()    第23节:ES6+ of()    第24节:ES6+ find()和findIndex()    第25节:ES6+ copyWithin()    第26节:ES6+ fill()    第27节:ES6+ isArray()    第28节:ES6+ 对象的扩展    第29节:ES6+ flat()    第30节:ES6+ 可选链操作符    第31节:ES6+ Object.is()    第32节:ES6+ Object.assign()    第33节:ES6+ Object.keys()    第34节:ES6+ Object.values()    第35节:ES6+ Object.entries()    第36节:ES6+ 数据结构扩展    第37节:ES6+ Set    第38节:ES6+ WeakSet    第39节:ES6+ Map    第40节:ES6+ WeakMap    第41节:ES6+ Symbol    第42节:ES6+ for...of    第43节:ES6+ 迭代协议    第44节:ES6+ 实现一个简版的 Promise    第45节:ES6+ Promise 基础    第46节:ES6+ Promise 进阶    第47节:ES6+ Generator 基础    第48节:ES6+ Generator 函数应用    第49节:ES6+ async/await    第50节:ES6+ Class 前置知识    第51节:ES6+ Class    第52节:ES6+ Proxy    第53节:ES6+ Reflect(一)    第54节:ES6+ Reflect(二)    第55节:ES6+ 模块化(一)    第56节:ES6+ 模块化(二)    第57节:ES6实战1-实现Vue3 reactive 源码    第58节:ES6实战2-实现 Vue3 effect 源码    第59节:ES6 实战2-封装请求    第60节:ES6+ 实战3-代码整洁之道    第61节:ES6 Map原理分析    第62节:ES6module语法加载importexport    第63节:ES6的循环与可迭代对象示例详解