2

我对 es2016 中的功能有点困惑,尽管与andclass相比,它被认为只是用于创建类的语法糖,但在某些情况下的行为是不同的,特别是 - 不能调用类与函数相同,似乎没有办法找出函数是类构造函数还是简单函数,而不使用和.functionprototypetoString/^class/ RegExp

假设示例:

class Foo {
    constructor () {
        this.name = 'foo';
    }
}
function Bar () {
    this.name = 'bar';
}

function doSmth (anyArg) {
    if (typeof anyArg === 'function') {
        var obj = { someProp: 'qux' };
        anyArg.call(obj);
        return obj;
    }
    // ...
}


doSmth(Bar);
doSmth(Foo); // Class constructor Foo cannot be invoked without 'new'

typeof 'function',但不能将其作为函数调用!好的。

这是我的两个问题:

  1. 有什么方法可以调用与覆盖上下文Foo相同的构造函数吗?Barthis
  2. 有什么方法可以检测到anyArg类的构造函数,以便我可以在我的doSmth函数中以不同的方式处理它。没有toStringand RegExp因为在这种情况下性能损失会很大)。然后我可以用它Reflect.construct来初始化新实例,并用实例中的值Object.assign扩展我的obj变量。

谢谢你,亚历克斯

4

3 回答 3

1

对这两个问题都没有。

以下是 Angular 1.x 检测类的方式:

function isClass(func) {
  // IE 9-11 do not support classes and IE9 leaks with the code below.
  if (msie <= 11 || typeof func !== 'function') {
    return false;
  }
  var result = func.$$ngIsClass;
  if (!isBoolean(result)) {
    // Support: Edge 12-13 only
    // See: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/6156135/
    result = func.$$ngIsClass = /^(?:class\b|constructor\()/.test(stringifyFn(func));
  }
  return result;
}

不幸的是,这是最好的解决方案。它甚至在 Firefox 中也不起作用。

于 2016-11-17T14:19:11.133 回答
0

我不知道如何做你在第一个问题中提出的问题。

对于第二个问题,您实际上确定了一种方法来自己区分差异。类构造函数和用作构造函数的函数之间的区别之一是前者在不使用new关键字时会出错,而后者则不会。

所以,如果我们使用 try/catch,我们可以大致做你想做的事:

class Foo {
    constructor () {
        this.name = 'foo';
    }
}
function Bar () {
    this.name = 'bar';
}

function doSmth (anyArg) {
    if (typeof anyArg === 'function') {
        var obj = { someProp: 'qux' };
        try {
          anyArg.call(obj);
        } catch(e) {
          var x = Reflect.construct(anyArg, []);
          Object.assign(obj, x);
        }
        return obj;
    }
}


doSmth(Bar);
doSmth(Foo);

需要明确的是,我并不是说这是一个好主意、好代码,或者它具有您正在寻找的性能,但我想我会指出这种可能性确实存在。

于 2016-11-17T14:00:19.830 回答
0

如果您担心 RegEx 的性能损失,请使用substring(). 如果您仍然关心字符串操作的性能,那么请考虑另一种实际区分函数类型的语言。在 JavaScript 中,它们都是function.

class Foo {
  constructor() {
    this.name = 'foo';
  }
}

function Bar() {
  this.name = 'bar';
}

function doSmth(anyArg) {
  if (typeof anyArg === 'function') {
    var obj = {
      someProp: 'qux'
    };
    if (anyArg.toString().substring(0, 5) === 'class') {
      Object.assign(obj, new anyArg());
    } else {
      anyArg.call(obj);
    }
    return obj;
  }
  // ...
}

var bar = doSmth(Bar);
var foo = doSmth(Foo);

console.log(bar);
console.log(foo);

于 2016-11-17T14:21:39.820 回答