Может ли какой-нибудь гений сказать мне, что происходит в этом маленьком коде? Из секретов 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)