Подтвердить что ты не робот

Как я могу предварительно задать аргументы в вызове функции JavaScript? (Приложение с частичной функцией)

Я пытаюсь написать функцию JavaScript, которая вернет свой первый аргумент (функцию) со всеми остальными его аргументами в качестве заданных параметров для этой функции.

Итак:

function out(a, b) {
    document.write(a + " " + b);
}

function setter(...) {...}

setter(out, "hello")("world");
setter(out, "hello", "world")();

Выведет "привет мир" дважды. для некоторой реализации setter

У меня возникла проблема с манипулированием массивом аргументов при первой попытке, но, похоже, это будет лучший способ сделать это.

4b9b3361

Ответ 1

Прежде всего, вам нужно частичное - есть разница между частичным и карри - и вот все, что вам нужно, без рамки:

function partial(func /*, 0..n args */) {
  var args = Array.prototype.slice.call(arguments, 1);
  return function() {
    var allArguments = args.concat(Array.prototype.slice.call(arguments));
    return func.apply(this, allArguments);
  };
}

Теперь, используя ваш пример, вы можете делать то, что вам нужно:

partial(out, "hello")("world");
partial(out, "hello", "world")();

// and here is my own extended example
var sayHelloTo = partial(out, "Hello");
sayHelloTo("World");
sayHelloTo("Alex");

Функция partial() может использоваться для реализации, но не выполняется. Вот цитата из сообщение в блоге о разнице:

Если частичное приложение принимает функцию и из нее строит функцию, которая принимает меньше аргументов, currying строит функции, которые принимают несколько аргументов по составу функций, каждый из которых принимает один аргумент.

Надеюсь, что это поможет.

Ответ 2

Является ли ваш javascript тем, что вы ищете?

Ответ 3

Если вы используете Dojo, вы просто вызываете dojo.hitch(), что делает почти то, что вы хотите. Почти; потому что он также может использоваться для упаковки контекста. Но ваш пример первый:

dojo.hitch(out, "hello")("world");
dojo.hitch(out, "hello", "world")();

Также как:

var A = {
  sep: ", ",
  out: function(a, b){ console.log(a + this.sep + b); }
};

// using functions in context    
dojo.hitch(A, A.out, "hello")("world");
dojo.hitch(A, A.out, "hello", "world")();

// using names in context
dojo.hitch(A, "out", "hello")("world");
dojo.hitch(A, "out", "hello", "world")();

dojo.hitch() является частью базы Dojo, поэтому, как только вы включили dojo.js, она есть для вас.

Другое общедоступное средство доступно в модуле dojox.lang.functional.curry(зарегистрировано в Функциональное удовольствие в JavaScript с Dojo Просто посмотрите на эту страницу для "curry" ). В частности, вы можете посмотреть на curry() и partial().

curry() накапливает аргументы (как в вашем примере), но с одной разницей: как только законность выполняется, она вызывает функцию, возвращающую значение. Реализация вашего примера:

df.curry(out)("hello")("world");
df.curry(out)("hello", "world");

Обратите внимание, что последняя строка не имеет "()" в конце — он вызывается автоматически.

partial() позволяет произвольно заменить аргументы:

df.partial(out, df.arg, "world")("hello");

Ответ 4

Используя Javascript apply(), вы можете изменить function prototype

Function.prototype.pass = function() {
    var args = arguments,
        func = this;
    return function() {
        func.apply(this, args);
    }
};

Затем вы можете называть его out.pass('hello','world')

apply принимает массив для второго аргумента/параметра.

arguments - это свойство, доступное внутри функции, которое содержит все параметры в структуре массива, как структура.

Другим распространенным способом сделать это является использование bind

loadedFunc = func.bind(this, v1, v2, v3);

затем

loadedFunc() === this.func(v1,v2,v3);

этого рода достаточно, хотя и немного уродливого.

Ответ 5

** EDIT: см. Ответ Джейсона Бэннинга. Этот ответ на самом деле показывает под-парный способ цепочки многочисленных вызовов, а не один исходящий вызов с предустановками для некоторых аргументов. Если этот ответ на самом деле помогает с аналогичной проблемой, вы должны обязательно использовать заявку и позвонить, как рекомендует Джейсон, вместо неясного способа использования eval, который я придумал. **

Хорошо... ваш выход действительно напишет "undefined" много в этом... но это должно быть близко к тому, что вы хотите:

function out(a, b) {
    document.write(a + " " + b);
}

function getArgString( args, start ) {
    var argStr = "";
    for( var i = start; i < args.length; i++ ) {
        if( argStr != "" ) {
            argStr = argStr + ", ";
        }
        argStr = argStr + "arguments[" + i + "]"
    }
    return argStr;
}

function setter(func) {
    var argStr = getArgString( arguments, 1 );
    eval( "func( " + argStr + ");" );
    var newSettter = function() {
        var argStr = getArgString( arguments, 0 );
        if( argStr == "" ) {
            argStr = "func";
        } else {
            argStr = "func, " + argStr;
        }
        return eval( "setter( " + argStr + ");" );
    }
    return newSettter;
}

setter(out, "hello")("world");
setter(out, "hello", "world")();

Я бы, вероятно, переместил код в getArgString в функцию setter, хотя... немного безопаснее, так как я использовал 'eval's.

Ответ 6

Вы можете использовать Function.prototype.bind(). Это дополнение ES5.

В дополнение к общей утилите настройки контекста функции (this значение), он также может устанавливать частичные аргументы.

function out(a, b) {
  document.write(a + " " + b);
}

function setter(func) {
  return func.bind.apply(func, [window].concat([].slice.call(arguments).slice(1)));
}

setter(out, "hello")("world");
setter(out, "hello", "world")();

Ответ 7

function myLog(arg1,arg2,arg3){
    return function(){
        //you can use the arguments from the parent scope
        console.log(arg1+" "+arg2+" "+arg3);
    };
}
var passMeAnywhere = myLog(1,2,3);
//execute the function, args will be in the immediate lexical scope.
passMeAnywhere();
//One of the previous posts showed a way for context binding
//Context binding allows any context
//New is not required with binding