美文网首页
ES 6 class 相关用法

ES 6 class 相关用法

作者: YeLqgd | 来源:发表于2018-11-22 15:36 被阅读0次

上篇笔记简单对比了,从 ES 5 到 ES 6 类的写法的变化:1、增加了 class 语法糖,而不必再繁琐地先写构造函数然后再在构造函数的 prototype 上添加属性或方法;2、通过 static 关键字增加了静态方法的写法。以及留下一个疑问:那些介绍 ES 6 的书上写的「ES 6 的继承机制与 ES5 完全不同,ES 6 的机制是先由父类创建 this 值,然后再由子类的 contructor 去修改这个值」,这个机制提现在代码实现上究竟是怎样的。我去试了下 Babel,然而看了半天发现 Babel 对 ES 6 的继承的转码实现本质上也依然是上篇笔记里提到的「寄生组合式继承」的加强版:将一些可重用的过程抽象成 _createClassdefineProperties_possibleConstructorReturn_inherits_classCallCheck 等方法,但本质上还是 ES 5 的继承机制。所以如果有谁知道 ES 6 的继承机制体现在代码上究竟是怎样,或者说能这种机制通过 ES 5 的代码没法实现,求告知。

下面稍微详细地介绍一下 ES 6 中类的相关用法,在此之前先了解下 classfunction 的不同:

  • 函数声明可以被提升,而 class 声明生效的机制与 let 一致:
console.log(A) // ReferenceError: A is not defined
class A {}
  • 类声明中所有代码都默认运行在严格模式下,且无法「关闭」这种「开关」
  • 类中所有方法都是不可枚举的:
class A {
  method1() {
    console.log('I am not enumerable')
  }
}
console.log(Object.keys(A.prototype)) // []

function B() {}
B.prototype.method1 = function() {
  console.log('I am enumerable')
}
console.log(Object.keys(B.prototype)) // ['method1']
  • 使用除关键字 new 以外的方式调用类都会报错:
class A {}
A() // Uncaught TypeError: Class constructor A cannot be invoked without 'new'

Babel 中通过 _classCallCheck 这个方法实现此功能。

  • 在类的内部修改类名会报错:
class A {
  constructor() {
    A = 'B'  // Uncaught SyntaxError: Identifier 'A' has already been declared
  }
}
A = B // 但在声明结束时可以修改

类表达式

我们知道函数除了可以声明生成以外还可以作为表达式,同样地,类也可以作为表达式,匿名或命名:

let Person = class {
  constructor(name) {
    this.name = name
  }
  
  sayName() {
    console.log(this.name)
  }
}
let person = new Person('chongErFei')
person.sayName // chongErFei

作为参数和返回值:

function extendsFunc(SubClass)  {
  return class SuperClass extends SubClass {
    // 省略 constructor 等价于 constructor(...args) { super(...args) }
    equippedFunc() {
      console.log('I am equipped by extendsFunc')
    }
  }
}

let EquippedPerson = extendsFunc(Person)
let ep = new EquippedPerson('mjmjxihrni')

ep.sayName() // mjmjxihrni
ep.equippedFunc() // I am equipped by extendsFunc

访问器属性、可计算成员名称

ES 5 中访问器属性需要 Object.defineProperty 来定义,需要写一串很繁琐的代码,而 ES 6 中可以通过直接在属性名前加 get 或是 set 来定义 gettersetter;其实访问器属性在普通的对象字面量就支持,可计算成员以及生成器方法也是,在类里就更不用说了:

let propertyName = 'name'
let methodName  = 'tellAge'
class Person {
  constructor(name, age) {
    this[propertyName] = name
    this.age = age
  }

  get upperCaseName() {
    return this.name.toUpperCase()
  }
  [methodName]() {
    console.log(this.age)
  }
}

let p = Person {name: "lll", age: 24}

p.upperCaseName // LLL
p[methodName] // 24

super

  • super 只能在派生类中使用,否则会报错
  • 派生类的 constructor 中使用 this 前,一定要先调用 super()
  • super 在派生类中有两种含义,在派生类的 constructor 中出现时代表父类的 constructor;而在实例方法中出现时表示父类的 prototype

Symbol.species 属性

Symbol.species 是众多内部 Symbol 的一个,它是一个静态访问器属性,返回值是一个构造函数,ES 6 中 ArrayArrayBufferMapPromiseRegExpSetTyped arrays 等内建类型都有这个属性,如果在自定义的类中实现这个属性,那么它看起来可能是

class MyClass {
  static get [Symbol.species]() {
    return this
  }

  constructor(value) {
    this.value = value
  }

  clone() {
    return new this.constructor[Symbol.species](this.value)
  }
}

,这个属性在我们需要继承内建对象时有用,假如我们现在想构建一个以 Array 为基类的特殊数组:

class MyArray extends Array {
  //  ...
}
let items = new MyArray(1, 2, 3, 4),
    subItems = items.slices(1, 3)

console.log(items instanceof MyArray) // true
console.log(subItems instanceof MyArray) // true

正常情况下,Array.slice() 的返回值应该是一个 Array 类型的,现在它成了 MyArray 类型,这里我们就可以通过重写派生类的 Symbol.species 属性来使凡是调用基类的方法都使用 Array 的实例而不用 MyArray

class MyArray extends Array {
  static get [Symbol.species]() {
    return Array
  }
}
let items = new MyArray(1, 2, 3, 4),
    subItems = items.slices(1, 3)

console.log(items instanceof MyArray) // true
console.log(subItems instanceof MyArray) // false
console.log(subItems instanceof Array) // true

一般说来,只要想在类方法中调用 this.constructor,都应该用 this.constructor[Symbol.species] 从而可以让以此类为基类的派生类改写 [Symbol.species] 属性。

相关文章

  • ES 6 class 相关用法

    上篇笔记简单对比了,从 ES 5 到 ES 6 类的写法的变化:1、增加了 class 语法糖,而不必再繁琐地先写...

  • class 相关

    class 基本用法[https://es6.ruanyifeng.com/#docs/class] static...

  • 测试

    接下来更新关于es6 class相关

  • 前端知识网络

    es6相关:generater,async/await, set,map,etc,class angular相关:...

  • Es6 中class的理解

    参考文档ECMAScript 6 入门。 1、对于class Es6的用法可能我们平常用的比较熟悉,但是真正...

  • ES6 class与继承

    class是什么 class是定义类的方法。ES6之前用构造函数的方式定义类,ES6引入了class。 class...

  • 使用ES5实现ES6的Class

    ES5的寄生组合式继承 ES6的Class 关于Class的语法推荐看这里:es6.ruanyifeng.com/...

  • 26- class 类与继承

    1、ES5 中基于原型的构造函数 2、ES6 的 class关键字 ES6 引入了 Class(类)这个概念,作为...

  • es6 class类的用法

    es6 class基础用法 以前的JavaScript没有类的概念,它是基于原型的面相对象的语言。原型对象的特点就...

  • es5实现class类

    es5没有类,只有构造函数。ES6新增了class,用于创建类。本文通过es5来实现es6的class(一个Ani...

网友评论

      本文标题:ES 6 class 相关用法

      本文链接:https://www.haomeiwen.com/subject/nwhlqqtx.html