Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/362.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 什么是反映。让我们来做这件事,不是';以前不可行吗?_Javascript_Reflection - Fatal编程技术网

Javascript 什么是反映。让我们来做这件事,不是';以前不可行吗?

Javascript 什么是反映。让我们来做这件事,不是';以前不可行吗?,javascript,reflection,Javascript,Reflection,我试图找到一个很好的理由来使用Reflect.construct来实现一些我以前无法实现的值得注意的东西 我不是在寻找一个像这样的答案,因为这个例子似乎不是很有用。例如,我为什么要写作 function greetingFactory(name) { return Reflect.construct(Greeting, [name]); } 当我能写的时候 function greetingFactory(name) { return new Greeting(name); } ?

我试图找到一个很好的理由来使用
Reflect.construct
来实现一些我以前无法实现的值得注意的东西

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

function greetingFactory(name) {
  return Reflect.construct(Greeting, [name]);
}
当我能写的时候

function greetingFactory(name) {
  return new Greeting(name);
}
?

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

编辑:似乎我自己已经找到了一个用例,但我不确定它是否可靠,是否不会崩溃,但基本上我似乎可以使
成为新的。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())

最酷的是,
这个
与原型方法中的预期一样

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

函数func1(a、b、c){
这个。总和=a+b+c;
}
常量args=[1,2,3];
const object1=新的func1(…args);
const object2=Reflect.construct(func1,args);
const array1Proto=Reflect.construct(func1,args,Array);
console.log(object1)
console.log(object2)

console.log(arrayproto)
我一直在尝试整理
Reflect.construct的一个有用的应用程序。我想我可能已经找到了一些东西,但如果我能从其他走上类似道路的人那里得到这个想法,那就太好了

我的想法是,您可以使用
Reflect.construct
在实例化对象和预期对象之间插入
[[Prototype]]
。这将允许您隐藏属于预期的
[[Prototype]]
的属性和方法,而不会造成太大的干扰

function Wedge() {};

Wedge.prototype = Object.create(String.prototype);

Wedge.prototype.toUpperCase = function () {
    return "nope";
}

let someString = Reflect.construct(String, ['Foo Bar'], Wedge)

someString.toUpperCase() // "nope"

据我所知,Reflect.construct的三个用例是:

  • 在代理中使用它来获得默认行为(或获得稍微修改的默认行为)

  • 使用它可以避免在需要使用数组调用构造函数时创建和使用迭代器,数组的元素需要作为离散参数传递。你可以这么做

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

    t = Reflect.construct(Thing, theArray);
    
    不使用迭代器,这样做的工作量要小得多(这并不重要;这适用于时间至关重要的情况)。(与迭代器不同,
    construct
    只使用
    length
    并直接访问
    0
    1
    等属性。)

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

    t = Thing.apply(Object.create(Thing.prototype), theArray);
    
    它与ES5构造函数一起工作。(它不适用于通过
    类创建的ES2015+构造函数,但您不需要它-您可以使用上述两个选项之一。)

  • 在构造
    Error
    Array
    的子类型或web组件的实例时,使用它可以避免使用
    (有些人,在可能需要传输的项目中,有很好的理由支持这一点)。(也就是说,
    Reflect.construct
    也不可能是完美的多重填充。)


  • 这个主题已经晚了,但实际上可以在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())
    
    //ES6类版本
    类MyArray扩展了数组{
    peek last(){
    返回此[this.length-1];
    }
    }
    //ES5类版本
    函数MyArray(){
    //不需要使用new,因为该实例已被丢弃
    var retval=新数组();
    retval.\uuuu proto\uuuuu=MyArray.prototype;//这是关键行
    //在此处执行任何其他初始化以检索。
    返回返回;
    }
    MyArray.prototype=Object.create(Array.prototype{
    建造商:{
    对,,
    可写:对,
    值:MyArray
    },
    最后一个:{
    对,,
    可写:对,
    值:函数peekLast(){返回此[this.length-1];}
    }
    });
    MyArray.\uuuuu proto\uuuuuu=数组;
    

    我知道在ES6之前,
    \uuuuuu proto\uuuuuu
    从未出现在ES标准中,但它实际上是所有主要浏览器和引擎都支持的web标准。这就是实现它的原因。

    我不认为这是为了实现以前不可能实现的事情,而是为这类“元”操作提供统一的API。@FelixKling我认为API作为更长的操作方式的快捷方式是有效的,但我想我也想知道,除了可能是一条捷径之外,
    Reflect.construct
    是否解决了任何问题。@FelixKling我更新了答案,我想我可能已经找到了一个用例。“很酷的是,这与原型方法中的预期一样!”无论如何,这都是应该的,多亏了你对它们的调用方式。在上面使用
    Reflect.construct
    所做的一切就是确保
    new.target
    是为
    Bar
    Foo
    的调用设置的(这可能确实有用;这基本上是my#3的一个通用版本)。这与使用
    Object.setPrototypeOf()手动设置原型有何不同
    obj.\uuuuuu proto\uuuuuu=…
    有趣。对以下
    Reflect.construct
    polyfill有什么想法@trusktr-从哪方面考虑?F.e.它有多完整,缺少哪些功能(F.e.无法多填充)?@trusktr-在纯ES5环境中。,您无法正确地将
    Error
    Array
    子类化,因此使用
    Reflect。当您提供
    新的
    时,使用
    Error
    Array
    构造
    。target
    (第三个参数)不起作用(也不能)。在具有
    \uuuu proto\uuuu
    的ES5环境中(Firefox中的SpiderMonkey可以追溯到几年前,IE11中的Chakra),您可以,但特定的polyfill不会尝试这样做。不是批评