应用 es6 new.target 来对模仿抽象类

劈头

近来在运用 Symbol 来做为唯一值,发明 Symbol 没法举行 new 操纵,只能看成函数运用,只需举行了new 就会发作范例毛病

new Symbol()

// error
Uncaught TypeError: Symbol is not a constructor
    at new Symbol (<anonymous>)
    at <anonymous>:1:1

在不斟酌底层完成的情况下,在代码层面是不是能够完成一个函数只能够举行挪用而不能够举行 new 操纵呢?思索以后以下写出:

function disConstructor() {
  if (this !== window) {
    throw new TypeError(' disConstructor is not a constructor')
  }
  console.log('gogo go')
}

// 测试效果以下
disConstructor() // gogo go

new disConstructor()

// error
Uncaught TypeError:  disConstructor is not a constructor
    at new disConstructor (<anonymous>:3:15)
    at <anonymous>:1:1

假如运用 nodejs,window 能够切换为 global, 代码运转效果稳定,由于关于个人而言没有实用场景。因而就没有继续研讨下去,然则近来在重新翻阅 es6 时刻发明 new.target这个属性。

new.target 属性

引见(援用 mdn 文档)

new.target属性许可你检测函数或组织要领是不是是经由历程new运算符被挪用的。
在经由历程new运算符被初始化的函数或组织要领中,new.target返回一个指向组织要领或函数的援用。在一般的函数挪用中,new.target 的值是undefined。

如许的话 我们的代码就能够如许改成

function disConstructor() {
  // 一般的函数挪用中,new.target 的值是undefined。
  if (new.target) {
    throw new TypeError(' disConstructor is not a constructor')
  }
  console.log('gogo go')
}

获得与上述代码一样的答案。

深切

岂非 es6 专程增添的功用仅仅只能用于检查一下我们的函数挪用体式格局吗?
在查阅的历程种种发明了大多数都计划都是用 new.target 写出只能被继续的类。类似于完成java的笼统类。

class Animal {
  constructor(name, age) {
    if (new.target === Animal) {
      throw new Error('Animal class can`t instantiate');
    }
    this.name = name
    this.age = age
  }
  // 其他代码
  ...
}

class Dog extends Animal{
  constructor(name, age, sex) {
    super(name, age)
    this.sex = sex
  }
}

new Animal()
// error
Uncaught Error: Animal class can`t instantiate
    at new Animal (<anonymous>:4:13)
    at <anonymous>:1:1

new Dog('mimi', 12, '公')
// Dog {name: "mimi", age: 12, sex: "公"}

然则 java笼统类笼统要领须要重写,这个是没有计划的。因而在测试与运用的历程当中,却不测发明了超类能够在组织时代接见派生类的原型,应用起来。

class Animal {
  constructor(name, age) {
    console.log(new.target.prototype)
  }
  // 其他代码
  ...
}

之前运转时挪用须要重写的要领报错是如许写的。

class Animal {
  constructor(name, age) {
    this.name = name
    this.age = age
  }

  getName () {
    throw new Error('please overwrite getName method')
  }
}

class Dog extends Animal{
  constructor(name, age, sex) {
    super(name, age)
    this.sex = sex
  }
}

const pite = new Dog('pite', 2, '公')
a.getName()
// error
Uncaught Error: please overwrite getName method
    at Dog.getName (<anonymous>:8:11)
    at <anonymous>:1:3

但是此时应用 new.target ,我就能够应用 组织时代 对子类举行操纵报错。

class Animal {
  constructor(name, age) {
    // 假如 target 不是 基类 且 没有 getName 报错
    if (new.target !== Animal && !new.target.prototype.hasOwnProperty('getName')) {
      throw new Error('please overwrite getName method')
    }
    this.name = name
    this.age = age
  }
}

class Dog extends Animal{
  constructor(name, age, sex) {
    super(name, age)
    this.sex = sex
  }
}

const pite = new Dog('pite', 2, '公')
// error
Uncaught Error: please overwrite getName method
    at new Animal (<anonymous>:5:13)
    at new Dog (<anonymous>:14:5)
    at <anonymous>:1:1

此时能够把运转要领时刻发作的毛病提前到组织时代,虽然都是在运转期,然则该毛病触发机制要早伤害要大。反而对代码是一种庇护。

固然了,应用超类能够在组织时代接见派生类的原型作用远远不是那末简朴,必定是很壮大的,能够连系营业场景谈一谈明白和作用。

其他计划

增添 编辑器插件
proxy
润饰器

    原文作者:jump__jump
    原文地址: https://segmentfault.com/a/1190000019131068
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞