2016-06-21 65 views
4

我正在为一个项目进行代码转换,并遇到了不寻常的边界情况。为什么不能将函数的调用成员分配给变量

我有以下几点:

function a(func){ 
    return func.call() 
} 

的转码器要改变它各方面的原因:

function a(func){ 
    var tmp = func.call; 
    var res = tmp() 
    return res; 
} 

然而,调用tmp()回来了tmp is not a function。如果我只是通过这一行进行调试和暂停,tmp被定义为一个函数。

它与它的签名是否有关function call(){ [native code]}

是否还有其他函数会触发类似的错误?

有没有办法解决这个问题,除了干脆不做?

编辑: 我发现了另外一个情况下,它看起来像它可能是与对象的情况下做的事:

a = { toString: null }.propertyIsEnumerable 
a("toString") 

抛出了同样的错误。

编辑:一些上下文; 我正在编写代码转换器,它有一个非常具体的用例,代码的每一行都被分成最简单的组成部分。有可能我不能将它分离得比这更远。使用上面的例子,func.call()是一个成员访问操作,后跟一个调用表达式,我想将成员访问和调用表达式分离为两个单独的表达式。

+3

*任何*方法依靠'this'价值,包括本地' Function.prototype.call'方法,有这个问题。解决方案是将其绑定到对象,或不使用这种低劣的转码。 – Bergi

+0

为什么转码需要你改变功能? – MayorMonty

+0

有没有办法做到这一点,仍然分裂一个表达式,它的组成部分?例如'tmp(func)'而不是'tmp()' –

回答

5

如果你想存储在一个变量的方法,而不是做

var f = obj.mymethod; 
f(); 

你可以做

var f = obj.mymethod.bind(obj); 
f(); 
+0

优秀 - 这似乎是一个适用于所有成员函数(包括'call')的通用解决方案。不幸的是,我无法进一步分离,但这样做会很好。 –

+1

我将不得不与其他人一起说,如果你找到一种不需要分离这种方法的方法,它可能会更好。如果生成的代码直接说'obj.method()',Javascript会更喜欢。 – hugomg

+0

它是自动化工具的一部分,在这种情况下并不重要,但它是最简单的解释方式。本质上,该工具的目的是删除任何隐式控制流并用显式替换它。它也有其他用途 - 但这是所需的预处理。 –

相关问题