Может ли какой-нибудь гений сказать мне, что происходит в этом маленьком коде? Из секретов JavaScript-ниндзя

Я только начинаю JavaScript, и мне интересно, есть ли какие-то гении, которые могут помочь мне понять это по строкам?

1:  Function.prototype.bind = function(){
2:   var fn = this, 
3:      args = Array.prototype.slice.call(arguments), 
4:      object = args.shift();
5:   return function(){
6:   return fn.apply(object,
7:      args.concat(Array.prototype.slice.call(arguments)));
8:  };
9: };

Я только начинающий, но если вы можете научить меня, тогда вы потрясающий. Я знаю о прототипах, вызовах, сдвигах, немного применяю, чтобы вы могли пропустить новички (хотя я думаю, что вы не должны так любить других, которые едва могут попасть в JS).

Примечание. Я знаю, что здесь есть несколько "похожих кодов", которые задают аналогичный вопрос здесь, но я спрашиваю строку за строкой. и они не (не дублируются) (также вы можете пропустить строки 8 и 9):)

Ответ 1

Это частичная реализация в EcmaScript 3 метода EcmaScript 5 bind, который выполняет частичное приложение. Он делает

myObject.method.bind(myObject, 1, 2)(3, 4)

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

myObject.method(1, 2, 3, 4)

но это также более удобно, потому что вы можете сделать

var m = myObject.method.bind(myObject, 1, 2);
m(3, 4);
m(5, 6);

вместо

myObject.method(1, 2, 3, 4);
myObject.method(1, 2, 5, 6);

Nit: эти два не совсем эквивалентны, потому что если первый вызов myObject.method делает this.method = somethingElse;, тогда связанный метод все равно будет вызывать оригинал.

Чтобы разбить его:

Function.prototype.bind = function(){

Добавляет метод к встроенному типу функции.

var fn = this, 

Хранилища this, которые должны быть Function при нормальном использовании, чтобы его можно было использовать внутри замыкания.

args = Array.prototype.slice.call(arguments), 

Создает массив, содержащий аргументы bind.

  object = args.shift();

Удаляет первый аргумент из args и сохраняет его в object. Это будет использоваться как значение this для fn, когда оно будет применено позже.

 return function(){

возвращает функцию, которая действует как частично применяемый метод. Эта функция при вызове

return fn.apply(object,

вызывает функцию слева от .bind, передавая первый аргумент bind как this. apply - специальный отражающий метод функций, который позволяет вызывать функцию с массивом аргументов, аналогичных *args или **kwargs в python, или ... в Java.

  args.concat(Array.prototype.slice.call(arguments)));

передается как аргумент fn, аргументы bind, за которым следует аргумент закрытия.

Ответ 2

Скажем, мы имеем функцию

function hi(a, b) { alert('hi! '+(a+b)); }

Определите функцию для каждой функции (так что вы можете использовать, например, hi.bind())

1:  Function.prototype.bind = function(){

fn есть this, поэтому исходная функция (в нашем примере this = hi)

2:   var fn = this, 

arguments (аргументы функции) не являются нормальным массивом, поэтому следующим является метод преобразования его в массив, который содержит точно такие же элементы, как arguments

3:      args = Array.prototype.slice.call(arguments), 

сдвигает args, возвращая первый (который является контекстом, с которым вы хотите вызвать функцию)

4:      object = args.shift();

эта функция возвращает новую функцию

5:   return function(){

apply - это функция, которая позволяет вызывать функцию с заданным фокусом и аргументами. hi(2,3) равно hi.apply(window, [2,3])

6:     return fn.apply(object,

Функция будет вызываться с аргументами bind и любыми дополнительными аргументами, которые вы передаете функции, в которой мы находимся (возврат bind)

7:        args.concat(Array.prototype.slice.call(arguments)));
8:     };
9: };

So hi(2,3) равно (hi.bind(window, 2, 3))() равно (hi.bind(window, 2))(3)