2016-06-21 3 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]}?

Существуют ли другие функции, которые будут вызывать подобные ошибки?

Есть ли способ обойти это, кроме как просто не делать этого?

EDIT: я нашел еще один случай, похоже, это может быть связано с контекстом объекта:

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

бросает ту же ошибку.

EDIT: некоторый контекст; Я пишу транскодер, он имеет очень специфический прецедент, где каждая строка кода разделяется на простейшие составные части. Возможно, я просто не могу отделить его дальше этого. Используя приведенный выше пример, 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

Мне нужно будет присоединиться к другим, сказав, что это, вероятно, лучше, если вы выясните способ не отделять методы, подобные этому. Javascript предпочтет, если сгенерированный код просто сказал 'obj.method()' напрямую. – hugomg

+0

Это часть автоматизированного инструмента, в этой точной ситуации это не важно, но это был самый простой способ объяснить. По сути, цель этого инструмента - удалить любой неявный поток управления и заменить его явным. У этого есть и другие цели - но это требуется предварительная обработка. –

Смежные вопросы