Я боюсь, ты ушел в слегка неправильном направлении. Эта линия:
var slice = Function.call.bind(Array.prototype.slice);
никогда не называет Function
и никогда не организует его можно назвать позже. Единственное, что Function
используется для его call
собственности. Function
мог бы быть Object
или Date
или RegExp
или любой другой функцией, или мог быть Function.prototype
; не имеет значения. Function.prototype
было бы более прямым и, возможно, менее запутанным.
Это немного сложно объяснить, потому что она включает в себя два слоя борьбы с this
, где this
разные вещи в разное время:
call
функция вызывает функции с определенным this
значение, которое вы даете ему, как его первый аргумент, передавая любые другие аргументы, которые вы ему даете. Например:
function foo(arg) {
console.log("this.name = " + this.name + ", arg = " + arg);
}
var obj = {name: "bar"};
foo.call(obj, "glarb"); // "this.name = bar, arg = glarb"
Там, потому что мы назвали call
на foo
, call
называется foo
с this
набором для obj
и проходящей вдоль "glarb"
argment.
call
знает, какую функцию он должен вызывать, исходя из того, что this
во время вызова call
. foo.call
this
в течение call
до foo
.Это может привести к путанице, так что давайте диаграмме:
foo.call(obj, "glarb")
звонки call
:
call
видит this = foo
и аргументы obj
и "glarb"
call
вызовы this
(который foo
):
foo
this = obj
и один аргумент "glarb"
Что касается slice
, вы обычно видите call
используется вместе с ним используется для создания массива из чего-то array- как, что на самом деле не является массивом:
var divArray = Array.prototype.slice.call(document.querySelectorAll("div"));
или
var divArray = [].slice.call(document.querySelectorAll("div"));
Здесь мы указываем call
с this
, установленным в Array.prototype.slice
(или [].slice
, что является той же функцией) и передает в коллекцию, возвращаемую querySelectorAll
в качестве первого аргумента. call
вызывает функцию, которую он видит как this
, используя свой первый аргумент как this
для этого вызова и проходящий через любой другой.
Итак, это первый слой this
.
bind
другая функция, что функции есть, и это похоже на call
но разные: Где call
вызовов целевой функция с заданной this
и аргументами, bind
создает и возвращает новой функции, которая будет делать, если вы назови это. Возвращаясь к нашему примеру foo
:
function foo(arg) {
console.log("this.name = " + this.name + ", arg = " + arg);
}
var obj = {name: "bar"};
var fooWithObjAndGlarb = foo.bind(obj, "glarb");
fooWithObjAndGlarb(); // "this.name = bar, arg = glarb"
Это называется связывания вещи (obj
и "glarb"
аргумент) в foo
.
В отличие от call
, поскольку bind
создает новую функцию, мы можем добавить аргументы позже:
Хорошо, теперь у нас есть все наши рабочие части. Так что происходит в вашем коде? Давайте разбить его на части:
// Get a reference to the `call` function from the `call` property
// on `Function`. The reason `Function` has a `call` property is that
// `Function` is, itself, a function, which means its prototype is
// `Function.prototype`, which has `call` on it.
var call = Function.call;
// Get a reference to the `slice` function from `Array.prototype`'s `slice` property:
var rawSlice = Array.prototype.slice;
// Create a *bound* copy of `call` that, when called, will call
// `call` with `this` set to `rawSlice`
var callBoundToSlice = call.bind(rawSlice);
(. callBoundToSlice
просто называется slice
в вашем вопросе, но я использую callBoundToSlice
, чтобы избежать путаницы) Переплет rawSlice
к call
был первый слой this
обработки, определения того, что call
будет см. как this
.Вызов callBoundToSlice
позвонит call
с this
, установленным в rawSlice
. Затем call
вызовет функцию, которую он видит, как (rawSlice
), используя свой первый аргумент как значение для this
во время вызова (второй уровень обработки this
) и передает любые дальнейшие аргументы.
Так наш forEach
с коллекцией из querySelectorAll
теперь может выглядеть следующим образом:
callBoundToSlice(document.querySelectorAll("div")).forEach(function(div) {
// Each div here
});
Это проходит collecton возвращенное querySelectorAll
в callBoundToSlice
, который вызывает call
с this
в rawSlice
, который вызывает Array.prototype.slice
с this
набором для Коллекция. Array.prototype.slice
использует this
для копирования массива.
Все, что сказал, используя slice
превратить массив подобных объектов в истинные массивы немного устарели. ES2015 представляет Array.from
метод, который может быть shimmed/polyfilled на двигателях JavaScript, которые не имеют его еще:
var divArray = Array.from(document.querySelectorAll("div"));
Это абсолютно нормально (рекомендуется, даже), чтобы ответить на свой вопрос, но он должен быть как на * Jeopardy! * Игровое шоу: отправьте свой вопрос как * вопрос *, и если у вас есть ответ, отправьте это как * ответ *. Сейчас трудно сказать, в чем ваш вопрос, и трудно сказать, чувствуете ли вы, что у вас уже есть ответ. –