Я читаю Eloquent Javascript и меня немного смущает этот пример частичной функции.Пожалуйста, помогите объяснить - PullRequest
5 голосов
/ 12 ноября 2011
function asArray(quasiArray, start) {
  var result = [];
  for (var i = (start || 0); i < quasiArray.length; i++)
    result.push(quasiArray[i]);
  return result;
}

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, [fixed, arguments])

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 */
};

Ответы [ 2 ]

2 голосов
/ 12 ноября 2011

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

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

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

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

EDIT:

Теперь, когда у нас есть 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; } 
0 голосов
/ 12 ноября 2011

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

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

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

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

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

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

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

...