【问题标题】:Extend object wrappers for modern primitives为现代原语扩展对象包装器
【发布时间】:2019-10-02 18:38:12
【问题描述】:

从 ES6 开始,类可以扩展特殊对象,如函数、数组和原始包装器。很简单:写一个扩展相应类型的类并使用它:

class MyNumber extends Number {
  constructor() {
    super(42)
  }
  
  square() {
    return this ** 2
  }
}

var x = new MyNumber()

console.log(typeof x, x + "", x.square() + "")

但 EcmaScript 也有一些新类型,例如 SymbolBigInt。它们仍然具有非原始包装类型,但您不能将它们用作构造函数,并且需要将原始包装显式包装到对象中:

var x = BigInt("42")
var y = Object(x)

console.log(typeof x, x + "", x + 1n + "")
console.log(typeof y, y + "", y + 1n + "")

try {
  var z = new BigInt("42")
} catch (e) {
  console.log(e.message)
}

如果我想扩展这样的包装器怎么办?定义一个类可以正常工作,但是如果我尝试创建一个对象,它会抛出 super 调用:

class MyBigInt1 extends BigInt {
  constructor() {
    super("42")
  }
}

try {
  var x = new MyBigInt1()
} catch (e) {
  console.log(e.message)
}

class MyBigInt2 extends BigInt {
  constructor() {
  }
}

try {
  var x = new MyBigInt2()
} catch (e) {
  console.log(e.message)
}

【问题讨论】:

    标签: javascript inheritance ecmascript-6


    【解决方案1】:

    来自the spec

    Symbol 构造函数 […] 不打算被子类化。

    同样来自the BigInt proposal

    BigInt 构造函数不能与 new 运算符一起使用或被子类化。

    实例化原始包装器已经够糟糕了,不要去扩展它们。

    一个技巧是不调用super()(您无法阻止抛出),而是自己创建对象(没有new),然后将其原型设置为您的自定义对象。就像你已经在your answer 中所做的那样:-)

    【讨论】:

    【解决方案2】:

    我找到了可能的解决方案,但仍在寻找更好的方法:

    class MyBigInt extends BigInt {
      constructor() {
        var res = Object(BigInt("42"))
        Object.setPrototypeOf(res, new.target.prototype)
        return res
      }
      
      square() {
        return this ** 2n
      }
    }
    
    var x = new MyBigInt()
    
    console.log(typeof x, x + "", x.square() + "")

    Symbol 的方法相同

    class MySymbol extends Symbol {
      constructor(description) {
        var res = Object(Symbol(description))
        Object.setPrototypeOf(res, new.target.prototype)
        return res
      }
      
      smth() {
        return `(${this.description})`
      }
    }
    
    var x = new MySymbol("qqq")
    
    console.log(typeof x, x.description, x.smth())
    
    var y = { [x]: 42 }
    
    console.log(y[x], y[x.toString()])

    【讨论】:

      猜你喜欢
      • 2022-01-23
      • 2011-10-24
      • 2014-08-28
      • 2017-03-06
      • 1970-01-01
      • 2018-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多