ES6相关知识——class

简介: JS查漏补缺系列是我在学习JS高级语法时做的笔记,通过实践费曼学习法进一步加深自己对其的理解,也希望别人能通过我的笔记能学习到相关的知识点。这一次我们来了解ES6相关知识——class

class定义类

实际上,类是“特殊的 函数”,就像你能够定义的 函数表达式函数声明一样,类语法有两个组成部分: 类表达式类声明
本质依旧是构造函数、原型链的语法糖
//  类的声明
class Person { }
// 类似于:
function Person { }

// 还有一个:类的表达式(但不常用)
var a = class {}

注意:函数声明类声明之间的一个重要区别在于,函数声明会提升,类声明不会。你首先需要声明你的类,然后再访问它(类表达式也是先声明后访问)

类的特性(和构造函数是一样的)

  1. 有显示原型prototype,也有隐式原型__proto__,还有constructor
  2. 通过typeof操作 类 打印出来的是 function而不是 class

class的构造方法

类的作用在于构建对象,而 constructor是一种用于创建和初始化 class创建的对象的特殊方法。
一个类只能有一个构造函数 (多个会报错)
class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
}
var p = new Person("a", 18)

如果不指定一个构造函数 (constructor) 方法,则使用一个默认的构造函数 (constructor)。

类的普通实例方法

一般通过创建出来的对象进行访问

类的实例方法定义:在class里定义方法相当于在原型上定义

class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  eating() {
    console.log(this.name + " eating~")
  }
}
var p = new Person("a", 18)
p.eating()

类的访问器方法定义:在class中定义 getter 和 setter 函数

class Person {
  constructor() {
    this._address = "广州市"
  }
  // 类的访问器方法
  get address() {
    console.log("拦截访问操作")
    return this._address
  }

  set address(newAddress) {
    console.log("拦截设置操作")
    this._address = newAddress
  }
}

类的静态方法

static 关键字用来定义一个类的一个静态方法。
通过类名进行访问,不用创建实例
通常用于为一个应用程序创建工具函数。
class Foo {
    static displayName = "Point";
    static classWrite() {
        console.log("hello world!");
    }
    classWrite() {
        console.log("你好,世界!");
    }
}

const p1 = new Foo();
console.log(p1.displayName) // undefined
Foo.classWrite();// hello world!

如果在实例上调用静态方法,就会抛出错误,表示该方法不存在。
因为静态方法只能通过类来调用,实例无法继承它的方法。
所以说如果静态方法中包含 this 关键字,通过类调用则这个 this 指向的是类,而不是实例。

在前面的文章可以看出我们实现继承是很麻烦的,但用class来实现继承很简单

用class实现继承

使用 extends 关键字在 类声明类表达式 中创建一个类作为另一个类的一个子类。
以前传参数给父类我们使用的是 call 方法,现在则要使用 super关键字(语法要求,不使用会报错)
super的使用:调用 父类 的构造函数并传参、调用 父类 上的方法
class Person {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a noise.`);
  }
}
// Student称之为子类(派生类)
class Student extends Person {  // Student 继承 Person
   constructor(name) {
    super(name); // 调用父类构造函数并传入 name 参数
  }

  speak() {
    console.log(`${this.name} barks.`);
  }
}

var p = new Student('a');
p.speak();// 'a barks.'

子类可以继承父类的方法,但如果子类重写了父类的方法,则打印的时候会输出子类重写后的方法

🚨注意:在子(派生)类的构造函数中使用this或者返回默认对象之前,必须先通过super调用父类的构造函数。

ES6转ES5的代码(了解)

因为有一些较低版本的浏览器不能识别比较新的语法,所以我们要将它转成ES5从而让浏览器识别(使用 babel工具可以将新的JS/TS代码转成ES5的代码)

继承内置类

继承系统的类并对其进行扩展

以array为例:

class MyArray extends Array {
  eating(){
    console.log("eatting~")
  }
}

const a = new MyArray(1, 2, 3);
const b = a.map(x => x);  // MyArray 继承了 Array 的方法,可以使用map方法

b instanceof MyArray; // true 
console.log(b); // MyArray(3) [ 1, 2, 3 ]
console.log(a.eating); // [Function: eating]

类的混入mixin

因为JavaScript的类只支持单继承,即只能继承一个父类
但我们想要继承多个父类,则该功能必须由父类提供

一个以超类作为输入的函数和一个继承该超类的子类作为输出可以用于在 ECMAScript 中实现混合:

function mixinRunner(BaseClass) {
  class NewClass extends BaseClass {  // 可以指定类的名称
    running() {
      console.log("running~")
    }
  }
  return NewClass
}

function mixinEater(BaseClass) {
  return class extends BaseClass {  // 也可以不指定类的名称
    eating() {
      console.log("eatting~")
    }
  }
}

class Person { }
class Student extends mixinEater(mixinRunner(Person)) {}
var p = new Student()
p.running() // running~
p.eating() // eatting~

在上述代码中,虽然没有mixin关键字,但我们利用JS原有的特性来实现混入的效果。

参考资料:
MDN
babel在线网站:https://babeljs.io/
coderwhy 的JS高级课程

目录
相关文章
ES6学习(7)class
ES6学习(7)class
|
4月前
|
存储 JavaScript 前端开发
ES6 class 类
【7月更文挑战第27天】
21 1
【TS】ts中的类:class
【TS】ts中的类:class
133 0
【TS】ts中的类:class
ES6 class使用方法
ES6 class使用方法
67 0
|
存储 JavaScript
【TS】class类和接口
【TS】class类和接口
110 0
|
JavaScript Java C++
ES6-Class如何优雅的进行“糖化”
这是一篇番外篇,其实他的主线是由一篇ES6-Class科普文章引发的“惨案”。虽然是番外篇,但是有些剧情还是不容错过的。 现在我们来进入番外篇的主线:ES6的Class是ES5构造函数的语法糖。
|
JavaScript 前端开发 Java
ES6_Extends如何对ES5的继承进行“糖化”
我用我拙劣的代码来将这层糖的成分细细分析一下。 下面一些方法,都是基于class被脱糖之后的分析。关于class是如何被脱糖的过程===>请先查看ES6-Class如何优雅的进行Prototype“糖化” 内容很精彩,但是不要忘记回来看这个。这个剧情也挺赤鸡的。
|
JavaScript 前端开发
ES6新特性 类(class)详解
ES6新特性 类(class)详解
143 0