Я читаю Eloquent Javascript, и меня немного смущает этот пример частичной функции. Пожалуйста, помогите объяснить

#javascript #function #partial

#javascript #функция #частичный

Вопрос:

 function asArray(quasiArray, start) {
  var result = [];
  for (var i = (start || 0); i < quasiArray.length; i  )
    result.push(quasiArray[i]);
  return resu<
}

function partial(func) {
  var fixedArgs = asArray(arguments, 1);
  return function(){
    return func.apply(null, fixedArgs.concat(asArray(arguments)));
  };
}

function compose(func1, func2) {
  return function() {
    return func1(func2.apply(null, arguments));
  };
}

var isUndefined = partial(op["==="], undefined);
var isDefined = compose(op["!"], isUndefined);
show(isDefined(Math.PI));
show(isDefined(Math.PIE));
  

Почему функция compose не может просто возвращать:

 func1(func2);
  

и выдайте правильный вывод. Я думал, что частичная функция, которая хранится в переменной isUndefined, уже возвращает func.apply(null, [исправлено, аргументы])

 var op = {
" ": function(a, b){return a   b;},
"==": function(a, b){return a == b;},
"===": function(a, b){return a === b;},
"!": function(a){return !a;}
/* and so on */
};
  

Комментарии:

1. где op объявлено? Можете ли вы добавить это в?

Ответ №1:

Оба partial и compose являются функциями более высокого порядка.

isUndefined вернет функцию, которая при вызове вызовет первоначально переданную функцию с исходными аргументами плюс любые новые аргументы, переданные при вызове.

Чтобы ответить на ваш вопрос, вы бы вызывали apply функцию, возвращаемую из partial , которая, в свою очередь, вызовет apply функцию, первоначально переданную partial .

Вы хотите compose вернуть функцию, которая при вызове вернет результат вызова первой функции, переданной второй функции в качестве аргумента (при передаче второй функции аргументы, переданные в compose вызов). Если compose возвращено func1(func2) , то вы бы присвоили результат вызова переменной isDefined .

Редактировать:

Теперь, когда у нас есть op , давайте попробуем разложить это:

 var isUndefined = partial(op["==="], undefined);
  

это эквивалентно

 var isUndefined = partial(function(a, b){return a === b;}, undefined);
  

isUndefined назначается функция, которая при вызове будет вызывать функцию, переданную в качестве первого аргумента partial , передавая undefined в качестве первого аргумента для этого вызова функции, за которым следуют аргументы, переданные функции isUndefined , т.е.

 partial(function(a, b){return a === b;}, undefined /* this will become 'a' when isUndefined is invoked */)(argumentForisUndefined /* this will become 'b' when isUndefined is invoked */);
  

isDefined составляется isUndefined с другой функцией, которая отрицает результат isUndefined .

 var isDefined = compose(op["!"], isUndefined);
  

эквивалентно

 var isDefined = compose(function(a){return !a;}, isUndefined);
  

что эквивалентно (переименованные переменные для ясности)

 var isDefined = compose(

    function(a){return !a;}, 

    partial(  /* partial function becomes 'a' passed to first function */
        function(b, c) {
            return b === c;
        }, 
        undefined /* undefined becomes 'b' passed to partial */
    ) 

)(argumentForisDefined /* argumentForisDefined becomes 'c' passed to partial */);
  

Если мы посмотрим на то, что у нас есть на данный момент, и заменим для удобства чтения, все сводится к функции, которая принимает аргумент и сравнивает его с неопределенным, отрицает результат и возвращает логическое

 var isDefined = function (b) { return !undefined === b; } 
  

Комментарии:

1. Хорошо, я думаю, что понимаю свое собственное замешательство. Я был сбит с толку тем, почему function.apply появлялся дважды. Но если функция Compose была просто func1 (func2), аргументы (в данном случае Math. Число ПИ или математика. PIE) никогда не будет передан частичной функции. Я прав?

2. Это верно — compose не вернул бы функциональную композицию из двух функций, которым она была передана изначально, но вернул бы результат их немедленного вызова, так что в любом случае не было бы необходимости передавать дополнительные значения partial ; это было бы уже вызвано.

Ответ №2:

Итак, давайте просто проанализируем это. Предполагая, что у нас есть эта функция compose:

 function compose(func1, func2) {
  return func1(func2.apply(null, arguments));
}
  

Что произойдет, когда вы будете использовать его подобным образом?

 a = compose(function(){console.log(1)}, function(){console.log(2)});
  

Вторая функция будет вызываться немедленно с выводом 2 , и сразу после этого первая функция будет вызываться с выводом 1 . a будет undefined , потому что первая функция ничего не возвращает.

То, что вы хотите сделать combine, это вернуть новую функцию, которая объединяет две другие функции и которую вы можете вызывать по желанию.

Выполнение всего вышеописанного в исходной композиции вернет новую функцию, которая при вызове с помощью a() будет выводить 2 , а затем 1 .