2016-03-29 2 views
0

Я столкнулся с this stackoverflow question о рекурсивном выравнивании массива JS. Вот принятый ответ:Рекурсивный Function.prototype.apply концептуальное понимание

function flatten() { 
    var flat = []; 
    for (var i = 0; i < arguments.length; i++) { 
     if (arguments[i] instanceof Array) { 
      flat.push.apply(flat, flatten.apply(this, arguments[i])); 
     } else { 
      flat.push(arguments[i]); 
     } 
    } 
    return flat; 
} 

flatten([[1], 2, [3, 4]]); // returns [1, 2, 3, 4] 

У меня возникли проблемы с пониманием, как flat.push.apply(...) и flatten.apply(...) работы.

Я понимаю, что функция будет только выйти, если нет элементов в массиве - сами массивы. Я также понимаю, что Function.prototype.apply() позволяет вам вызвать функцию, используя массив аргументов.

Я не понимаю, почему вы используете flat.push..., если flat будет установлен на [] при каждой итерации функции. Кроме того, какое значение имеет значение flat как контекст this?

Может кто-нибудь помочь объяснить, как работает flat.push.apply(flat, flatten.apply(this, arguments[i]));?

+0

«* если' flat' будет установлен на '[]' для каждой итерации функции. * "- это не итерация, это рекурсия. И каждый вызов имеет свои собственные локальные переменные. – Bergi

+0

"* какое значение имеет установка' flat', как этот контекст? * "- это контекст метода' push' * *, который является массивом, который будет нажат. Так же, как если вы регулярно вызываете 'flat.push (...)' * на 'flat' *. – Bergi

+0

'flat' не устанавливается на каждую итерацию, она устанавливается только один раз, перед циклом. – dandavis

ответ

2

Он использует flat.push безопасно, потому что push фактически вызывается в разных массивах каждый раз. Каждый раз, когда flatten выполняет, он создает новый массив с различной ссылкой, хранящейся в переменной flat, поэтому каждая рекурсия связана с другим массивом flat.

Установка flat как this контекст предоставляет массив, который будет называться push. Попробуйте установить его на null, и вы, вероятно, получите TypeError из-за незаконной операции - попробуйте позвонить push по телефону null.

Теперь для более сложной части. push принимает список аргументов, которые нужно добавить в массив, не так ли? Но иногда бывает нецелесообразно приводить эти аргументы один за другим, особенно если вы не знаете, сколько из них должно получить push, как в вашем случае, где размеры массивов, подлежащих выравниванию, различаются.

Именно поэтому автор этого кода вызывает push через apply с ссылкой на массив как второй аргумент - это возвращаемое значение flatten.apply(this, arguments[i]) - ссылка на массив, содержащий только числа к этому времени. Каждый номер этого массива помещается в flat, потому что apply называется push и передал весь список номеров этого массива через аргументы push.

Часть flatten.apply(this, arguments[i]) вызывается через apply по аналогичным причинам - она ​​использует arguments (объект, подобный массиву, каждая функция имеет), чтобы легко обрабатывать функции args. Передача this в первом аргументе apply здесь не имеет значения, потому что нет необходимости в this в flatten (this указывает на глобальный объект в вашем примере кода).

Смежные вопросы