Функция "slice" в прототипе Array ожидает, что this
будет ссылаться на массив, с которым она должна работать.Другими словами, если у вас есть реальный массив:
var myArray = [1, 2, 3];
и вы вызываете slice()
:
var sliced = myArray.slice(1);
Тогда в этом вызове slice()
, this
относится кмассив "myArray".Как отмечает Райнос в комментарии:
myArray.slice(1)
совпадает с
myArray.slice.call(myArray, 1);
Таким образом, когда вы используете call()
для вызова функции и передачи ее arguments
в качестве контекстаобъект, код slice()
работает на arguments
.Другие параметры, передаваемые через .call()
, являются просто параметром или параметрами самого slice()
.В моем примере выше обратите внимание, что я передал 1. функции.
Теперь, что касается второго вопроса, эта функция .invoke()
сначала изолирует аргументы, переданные после первых двух.Это означает, что когда вы используете _.invoke()
, вы передаете ему два или более аргумента: первый - это список для обработки, второй - метод, и (необязательные) последующие аргументы передаются методудля каждого элемента списка.
Этот вызов _.map()
сложен (и на самом деле я думаю, что в нем есть небольшая чепуха).Он выполняет итерации по списку, вызывая функцию для каждого значения в списке.Что эта функция делает, чтобы сначала определить, является ли параметр «method» действительно функцией.Если это так, то она вызывает эту функцию через .apply()
с элементом списка в качестве контекста.Если «метод» является , а не функцией, то он предполагает, что это имя свойства каждого элемента списка и что свойства являются функциями.
Так, например, с простым спискомэто довольно просто:
var myList = [1, 2, 3];
var result = _.invoke(myList, function(n) { return this * n; }, 2);
Это даст результат [2, 4, 6]
, потому что функция, которую я передал, умножает свой объект контекста (this
) на переданный параметр, и я передал 2 в вызове _.invoke()
.
С более сложным списком я могу использовать второй вариант _.invoke()
и вызвать метод для каждого объекта в списке:
var getName = function(prefix) { return prefix + " " + this.name; };
var list = [
{ name: "Bob", getName: getName },
{ name: "Sam", getName: getName },
{ name: "Lou", getName: getName }
];
var result = _.invoke(list, "getName", "Congressman");
, который вызовет "getNamemsgstr "работать с каждым объектом в списке и возвращать список из результатов.Эффектом будет список ["Congressman Bob", "Congressman Sam", "Congressman Lou"]
.
Теперь об этой ерунде.В коде для _.invoke()
:
return _.map(obj, function(value) {
return (method.call ? method || value : value[method]).apply(value, args);
});
Это подвыражение method || value
будет всегда возвращать значение "метода" или, по крайней мере, почти всегда исключать какой-то экзотический прием.Если method.call
является правдивым, то ссылка на method
также должна быть правдивой.Кроме того, если бы это был мой код, я бы осмотрел method
за пределами _.map()
обратного вызова, чтобы решение не приходилось принимать снова и снова.Может быть что-то вроде:
return _.map(obj, method.call ?
function(value) { method.apply(value, args); } :
function(value) { value[method].apply(value, args); }
);