2016-10-28 7 views
2

Я использую JavaScript-шпионскую библиотеку, simple-spy.Является ли `eval` единственным способом создания функций с динамически определяемой арностью в JavaScript?

Я обнаружил, что, когда шпионил данную функцию, в результате шпион всегда имеет арность 0.

Это создает проблему с моим использованием this currying function.

Итак, у меня есть submitted a pull-request that adds arity transparency to the spy library.

код выглядит следующим образом:

function spy(fn) { 
    const inner = (...args) => { 
     stub.callCount++; 
     stub.args.push(args); 
     return fn(...args); 
    }; 

    // ends up a string like 
    // 'a,b,c,d' 
    // depending on the `fn.length` 
    const stubArgs = Array(fn.length) 
     .fill(null) 
     .map((m, i) => String.fromCodePoint(97 + i)) 
     .join(); 

    const stubBody = 'return inner(...arguments);'; 

    // this seems to be the only way 
    // to create a function with 
    // programmatically specified arity 
    const stub = eval(
     // the wrapping parens is to 
     // prevent it from evaluating as 
     // a function declaration 
     `(function (${stubArgs}) { ${stubBody} })` 
    ); 

    stub.reset =() => { 
     stub.callCount = 0; 
     stub.args = []; 
    }; 

    stub.reset(); 

    return stub; 
} 

exports.spy = spy; 

Это похоже на работу.

Возможно ли это без использования eval?

Возможно ли до уменьшить использование eval еще менее того, что это?

Я знаю, что есть другие проблемы с этой реализацией шпиона. Это упрощенно и работает для моего использования.

+3

Вы можете использовать 'Function' и задать аргументы. Не намного лучше, но лучше. Вы также можете установить '.length' с помощью defineProperty для функций –

ответ

2

Как Benjamin писал, я использовал простой:

function spy(fn) { 
    const stub = (...args) => { 
     stub.callCount++; 
     stub.args.push(args); 
     return fn(...args); 
    }; 

    stub.reset =() => { 
     stub.callCount = 0; 
     stub.args = []; 
    }; 

    stub.reset(); 

    Object.defineProperty(stub, 'length', {value: fn.length}); 

    return stub; 
} 

exports.spy = spy; 

Гораздо, гораздо лучше выглядит.