2016-11-17 56 views
2

虽然与functionprototype相比,我们对es2016中的class功能有点困惑,但它的行为在某些情况下是不同的,特别是 - 类不能被称为相同的功能,似乎没有办法找出函数是类构造函数还是简单的函数,而不使用toString/^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',但不能把它作为一个功能!尼斯。

这里是我的2个问题:

  1. 有一些方法我可以调用Foo构造函数一样Bar与重写this背景?
  2. 有什么方法可以检测到anyArg是一个类的构造函数,因此我可以在我的doSmth函数中以不同方式处理它。没有toStringRegExp作为性能损失将是巨大的在这种情况下)。然后,我可以使用Reflect.construct来初始化新实例,并使用Object.assign来扩展我的obj变量与来自实例的值。

谢谢,亚历克斯

+2

FWIW,这听起来很疯狂,而我的)不知道到底是一个什么样接收和b)想强迫对象的构造类似。 – deceze

+0

[如何区分箭头函数,类和普通函数?](http://stackoverflow.com/a/31947622/1048572) – Bergi

回答

0

否这两个问题。

这里的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上不起作用。

+0

感谢您提供角度样本。 Yeap似乎确实是唯一一种检测类的方法。如果没有更好的解决方案,有人提供将接受这个答案。 – tenbits

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); 

要清楚,我并不是说这是一个好主意,好的代码,或者说,它有你要找的表现,但我想我会指出这种可能性确实存在。

+0

'try..catch'可能是一个解决方案,但这里我们不能确定这个异常是由作为函数调用一个类引起的,而不是由函数内部的某些代码引起的。从你的例子中,我们应该以某种方式解析异常的消息,但是消息是否跨浏览器统一? – tenbits

+0

绝对如此。你要么必须这样做,要么使用更多本地try/catch函数调用函数中的所有代码,这有其自身的问题。就像我说的,我并没有声称这种方法是完美的(我怀疑你会找到一个完美的解决方案,说实话),只是想提高完整性的可能性,以防万一它帮助其他人访问未来的页面。 – Hecksa

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);

+1

'anyArg.constructor === Function' so'anyArg.constructor()'总是返回一个无操作函数。 – thorn

+0

好点。我更新了它。 –

相关问题