Какая цель использования Function.call.apply в JavaScript?

Я просматривал Сад JavaScript, когда я наткнулся на хакер Function.call.apply, который используется для создания "быстрых, несвязанных оберток" ". В нем говорится:

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

function Foo() {}

Foo.prototype.method = function(a, b, c) {
    console.log(this, a, b, c);
};

// Create an unbound version of "method" 
// It takes the parameters: this, arg1, arg2...argN
Foo.method = function() {

    // Result: Foo.prototype.method.call(this, arg1, arg2... argN)
    Function.call.apply(Foo.prototype.method, arguments);
};

Я не понимаю, зачем вам нужно использовать функцию Function.call.apply, когда Function.apply будет достаточно. В конце концов, оба они семантически эквивалентны.

Ответы

Ответ 1

Нет, Function.call.apply и Function.apply в этом случае не совпадают.

Предположим, что исходный вызывающий вызов

Foo.method(t, x, y, z)

При вызове и применении вместе, как и в коде JavaScript Garden. Это выполняется

Function.call.apply(Foo.prototype.method, arguments);

который (свободно, записывая arguments в массив-нотации):

Function.call.apply(Foo.prototype.method, [t, x, y, z]);

который вызывает Function.call с помощью this==Foo.prototype.method:

Foo.prototype.method.call(t, x, y, z)

который вызывает Foo.prototype.method с this, установленным в t, и аргументы x, y и z. Милая. Также как в комментариях. Мы успешно сделали обертку.

Теперь предположим, что вы оставили только Function.apply вместо Function.call.apply, который, по вашему утверждению, семантически эквивалентен. У вас будет

Function.apply(Foo.prototype.method, arguments);

который (свободно)

Function.apply(Foo.prototype.method, [t, x, y, z]);

который вызывает функцию Function (ugh!) с this, установленную в Foo.prototype.method, и аргументы t, x, y и z.

Не то же самое.

Ответ 2

Это означает, что вы можете использовать методы из объекта на другом.

Хорошим примером является аргумент variable, который все функции имеют, как массив, а не массив, поэтому вы можете называть методы массива таким образом:

Array.prototype.join.call(arguments, ",");