Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/471.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在ES5中实现同样适用于ES2015类的“类扩展”函数(例如decorator函数)_Javascript_Ecmascript 6_Ecmascript 5 - Fatal编程技术网

Javascript 如何在ES5中实现同样适用于ES2015类的“类扩展”函数(例如decorator函数)

Javascript 如何在ES5中实现同样适用于ES2015类的“类扩展”函数(例如decorator函数),javascript,ecmascript-6,ecmascript-5,Javascript,Ecmascript 6,Ecmascript 5,我昨天问了一个类似的问题,它被标记为 由于上面的链接文件没有给出完整的答案,我今天问的同样的问题有点不同。。。并提供以下可能的解决方案: 我必须如何实现ES5函数extend它应该在下面的演示中扩展一个类,以便在不获取类构造函数的情况下也使用ES2015类baseClass不能在没有“new”错误的情况下调用 [编辑:函数extend将是传输的ES5库的一部分。该库本身随后可能会被使用ES5或>=ES2015的其他人使用-这两种情况都可以使用] // ES5 function (similar

我昨天问了一个类似的问题,它被标记为

由于上面的链接文件没有给出完整的答案,我今天问的同样的问题有点不同。。。并提供以下可能的解决方案:

我必须如何实现ES5函数extend它应该在下面的演示中扩展一个类,以便在不获取类构造函数的情况下也使用ES2015类baseClass不能在没有“new”错误的情况下调用

[编辑:函数extend将是传输的ES5库的一部分。该库本身随后可能会被使用ES5或>=ES2015的其他人使用-这两种情况都可以使用]

// ES5 function (similar to: constr => class extends constr {})
function extend(constr) {
  var ret = function () {
    constr.apply(null, arguments)
  }

  ret.prototype = Object.create(constr.prototype)

  return ret
}


// ES2015 code
const
  baseClass = class {},
  extendedClass = extend(baseClass)

new extendedClass() // <- Error: Class constructor baseClass cannot be invoked without 'new'
我会尝试使用Reflect.construct:

let extend = function (constr) {
    let ret;
    if(Reflect && Reflect.construct){
        ret = function(...args){
            let inst = Reflect.construct(constr, args, eval('new.target'));
            return inst;
        }
    } else {
        ret = function () {
        constr.apply(this, arguments)
        }
    }
    ret.prototype = Object.create(constr.prototype);
    ret.prototype.constructor = ret;
    return ret;
}

eval行只是使它在传输到ES5时不会出现语法错误。如果你想扩展你用extend创建的构造函数,这是必要的,否则原型就会丢失。

我认为这可能是一个不使用eval的解决方案。。。或新功能。。。你觉得怎么样

请在此处查找演示:


如果您已经在处理类,为什么要混合构造函数类型?上面的代码将是transpiled ES5库的一部分。这个库以后可能会被其他使用ES5或>=ES2015I的人使用我不明白这有什么区别?如果您使用的是transpiler,那么您可以创建类;如果您没有使用transpiler,那么它就不会是ES5环境,因为您有类。除非您想使用它来扩展传输的代码?让我们假设库中有一个函数decoratebaseClass,该函数在内部使用extend,可以用作ES2015 decorateclass{…}或ES5 decoratesMees5constructor,这两个函数都可以用于您的答案。这个解决方案的问题是,对以下代码的输出将是false而不是true:类A{};常数B=extendA;console.lognew B instanceofB@MinusFor:我想它一定是Reflect.construct,args,在上面的代码片段中派生出来的,然后它似乎可以工作,对吗?@Natasha噢,我用错了,它需要一个类似数组的对象,而不是散播参数。注意,您确实需要new.target,这样您就可以正确地设置原型了。。。但是,对于ES5来说,这不是有效的语法。你可以把它包在评估线上though@MinusFor谢谢,您的最新版本=>eval'new.target'运行良好。但是现在我们有一个问题,使用eval是不好的,甚至比使用新函数更糟糕。。。正如我在上面的解决方案中所做的那样。你知道如何用其他东西来替换eval'new.target'吗?我想这个.constructor在这种情况下可以工作,我现在想不出一个edge案例,但它似乎可以工作。
let extend = function (constr) {
    let ret;
    if(Reflect && Reflect.construct){
        ret = function(...args){
            let inst = Reflect.construct(constr, args, eval('new.target'));
            return inst;
        }
    } else {
        ret = function () {
        constr.apply(this, arguments)
        }
    }
    ret.prototype = Object.create(constr.prototype);
    ret.prototype.constructor = ret;
    return ret;
}
var hasReflection =
  typeof Reflect === 'object'
    && Reflect
    && typeof Reflect.construct === 'function'

function extend(baseClass) {
  var ret = function () {
    if (!(this instanceof ret)) {
      throw new Error("Class constructor cannot be invoked without 'new'")
    }

    var type = this.constructor

    return hasReflection
      ? Reflect.construct(baseClass, arguments, type)
      : void(baseClass.apply(this, arguments))
  }

  ret.prototype = Object.create(baseClass.prototype, {
    constructor: {
      value: ret
    }
  })

  return ret
}