Reflect.construct 可以让我们做什么以前无法做到的事情?

tru*_*ktr 4 javascript reflection

我试图找到一个很好的理由来Reflect.construct实现一些我以前无法实现的值得注意的事情。

我不是在寻找像这里的答案,因为那个例子似乎不是很有用。例如,我为什么要写

function greetingFactory(name) {
  return Reflect.construct(Greeting, [name]);
}
Run Code Online (Sandbox Code Playgroud)

当我可以写

function greetingFactory(name) {
  return new Greeting(name);
}
Run Code Online (Sandbox Code Playgroud)

?

你知道任何值得注意的用例Reflect.construct吗?

编辑:似乎我自己找到了一个用例,但我不确定它是否可靠以及它是否不会分崩离析,但基本上似乎我可以new.target通过编写它们来使用 ES5 样式的类这个:

function Foo() {
  console.log('Foo, new.target:', new.target)
  this.name = "foo"
}

Foo.prototype.sayHello = function sayHello() {
  return this.name
}

function Bar() {
  console.log('Bar, new.target:', new.target)
  let _ = Reflect.construct(Foo, [], new.target)
  _.name = _.name + " bar"
  return _
}

Bar.prototype = Object.create(Foo.prototype)

Bar.prototype.sayHello = function() {
  return "Hello " + Foo.prototype.sayHello.call(this) + "!"
}

function Baz() {
  console.log('Baz, new.target:', new.target)
  let _ = Reflect.construct(Bar, [], new.target)
  _.name = _.name + " baz"
  return _
}

Baz.prototype = Object.create(Bar.prototype)

Baz.prototype.sayHello = function() {
  return Bar.prototype.sayHello.call(this) + " Hello again!"
}

let baz = new Baz

console.log(baz.sayHello())
Run Code Online (Sandbox Code Playgroud)

很酷的一点是它this在原型方法中符合预期!

T.J*_*der 5

我所知道的仅有的三个用例Reflect.construct是:

  1. 在代理construct陷阱中使用它来获得默认行为(或获得稍微修改的默认行为)。

  2. 当您需要使用数组调用构造函数时,使用它来避免创建和使用迭代器,该数组的元素需要作为离散参数传递。你可以

    t = new Thing(...theArray);
    
    Run Code Online (Sandbox Code Playgroud)

    但这涉及创建和使用迭代器,而

    t = Reflect.construct(Thing, theArray);
    
    Run Code Online (Sandbox Code Playgroud)

    不使用迭代器,它的工作量要少得多(通常并不重要;这是在您知道时间至关重要的情况下)。(代替一个迭代的,construct只是使用length并直接访问01等属性。)

    在 ES2015 之前,这两个选项都不可用。相反,您必须这样做:

    t = Thing.apply(Object.create(Thing.prototype), theArray);
    
    Run Code Online (Sandbox Code Playgroud)

    与 ES5 构造函数一起使用。(它不适用于通过创建的 ES2015+ 构造函数class,但您不需要它——您可以改用上述两个选项之一。)

  3. 使用它来避免class在构造ErrorArray或 Web 组件的子类型的实例时使用(有些人不喜欢使用class,并且在可能需要转译的项目中对此有很好的论据)。(也就是说,Reflect.construct也不能完美地填充。)


小智 0

它接受其原型应在Reflect.constructor第三个参数中使用的构造函数。尝试下面的代码并查看array1Proto中的原型。尽管开头是 Object/func1,但它将 Array 设置为构造函数。

    function func1(a, b, c) {
      this.sum = a + b + c;
    }
    
    const args = [1, 2, 3];
    const object1 = new func1(...args);
    const object2 = Reflect.construct(func1, args);
    const array1Proto = Reflect.construct(func1, args, Array);
    
    console.log(object1)
    console.log(object2)
    console.log(array1Proto)
Run Code Online (Sandbox Code Playgroud)