Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
js_exams.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
359 Кб
Скачать
☆
  1. Методы и свойства функций. Как с ними работать и когда их применять?

length

— количество агрументов, которые функция ожидает.

(function( a, b ){}).length; // 2

apply( thisArg[, argsArray] )

— метод вызывает функцию с заданным this и аргументами, переданными как массив.

Преимущество apply перед call отчётливо видно, когда мы формируем массив аргументов динамически. Например, в JavaScript есть встроенная функция Math.max(a, b, c...), которая возвращает максимальное значение из аргументов:

Math.max.apply( null, [1, 2, 3] ); // 3

call( thisArg[, arg1[, arg2[, ...]]] )

— метод вызывает функцию с заданным this и аргументами.

function showFullName() {

alert( this.firstName + " " + this.lastName );

}

var user = {

firstName: "Василий",

lastName: "Петров"

};

showFullName.call(user) // "Василий Петров"

После контекста в call можно передать аргументы для функции. Вот пример с более сложным вариантом showFullName, который конструирует ответ из указанных свойств объекта:

var user = {

firstName: "Василий",

surname: "Петров",

patronym: "Иванович"

};

function showFullName(firstPart, lastPart) {

alert( this[firstPart] + " " + this[lastPart] );

}

showFullName.call(user, 'firstName', 'surname') // "Василий Петров"

showFullName.call(user, 'firstName', 'patronym') // "Василий Иванович"

bind( thisArg[, arg1[, arg2[, ...]]] )

— (EcmaScript 5) создаёт новую функцию с привязкой к заданному this и предопределёнными агрументами, если заданы (они будут прибавлены к каждому вызову новой функции, причем встанут перед теми, которые указаны при вызове).

var user = {

firstName: "Вася",

sayHi: function() {

alert( this.firstName );

}

};

setTimeout(user.sayHi.bind(user), 1000); // "Вася"

Методы bind и call/apply близки по синтаксису, но есть важнейшее отличие. Методы call/apply вызывают функцию с заданным контекстом и аргументами. А bind не вызывает функцию. Он только возвращает «обёртку», которую мы можем вызвать позже, и которая передаст вызов в исходную функцию, с привязанным контекстом.

Метод func.bind(thisArg, ...) может создавать обёртку, которая фиксирует не только контекст, но и ряд аргументов функции. Например, есть функция умножения двух чисел mul(a, b):

function mul(a, b) {

return a * b;

};

При помощи bind создадим функцию double, удваивающую значения. Это будет вариант функции mul с фиксированным первым аргументом:

var double = mul.bind(null, 2);

double(3); // = mul(2, 3) = 6

double(4); // = mul(2, 4) = 8

double(5); // = mul(2, 5) = 10

При вызове double будет передавать свои аргументы исходной функции mul после тех, которые указаны в bind, то есть в данном случае после зафиксированного первого аргумента 2.

  1. Что такое каррирование, как оно работает и зачем нужно? Что такое мемоизация?

Каррирование - это приём в функциональном программировании, позволяющий преобразовать функцию, заменив её несколько первых аргументов константными значениями, тем самым создав новую функцию с меньшим количеством аргументов на основе старой. Этот будет удобно применять в случае, когда первые несколько аргументов функции заранее известны, и указывать их при каждом вызове нет необходимости.

function sum(a, b) {

return a + b;

}

function sayTwoWords(word1, word2) {

console.log(word1 + " " + word2);

}

function curry(func, a) {

return function (b) {

return func(a, b);

};

}

var sayGoodbyeTo = curry(sayTwoWords, "Goodbye");

sayGoodbyeTo("Mary"); // "Goodbye Mary"

var minusThree = curry(sum, -3);

console.log(minusThree(13)); // 10

В JS функция при вызове может принимать произвольное количество аргументов, вне зависимости от того, сколько их было указанно при объявлении. Пользуясь этой возможностью, объявим куррирующую функцию с одним параметром func, в который будет передаваться каррируемая функция. Остальные же параметры будут значениями, на которые будут заменяться первые аргументы каррируемой функции. Эти значения мы будем извлекать из объекта arguments, в котором содержатся все значения аргументов функции, и записывать в массив. В возвращаемой функции нам необходимо вызвать каррируемую функцию, подставив в качестве первых аргументов значения из массива curryArgs, а в качестве остальных — значения, переданные в качестве параметров возвращаемой функции. Для этого воспользуемся методом apply, который позволяет вызвать функцию со значениями аргументов, которые переданы ему в массиве. Перед тем, как вызвать метод apply от каррируемой функции, преобразуем в массив объект arguments возвращаемой функции и склеим, при помощи метода concat, массив curryArgs c полученным массивом. Результат этой операции и передадим в качестве второго аргумента методу apply. В итоге функция curry примет вид:

function curry(func) {

var args = arguments, curryArgs = [];

for (var i = 1; i < args.length; i++) {

curryArgs[i - 1] = args[i];

}

return function () {

var argsArr = Array.prototype.slice.call(arguments, 0);

curryArgs = curryArgs.concat(argsArr);

return func.apply(this, curryArgs);

}

}

В ES2015 функцию каррирования можно записать короче:

function curry( func, ...curryArgs )

{

return ( ...rest ) =>

func( ...curryArgs, ...rest );

}

Примеры:

function multiply( x, y )

{

return x * y;

}

const double = curry( multiply, 2 );

double( 2 ); // 4

const double4 = ( x ) => multiply( x, 2 );

const double3 = ( y ) => multiply( 2, y );

Иногда наши рекурсивные или часто вызываемые функции очень сильно «тормозят» выполнение программы, потому что результаты промежуточных вычислений нигде не сохраняются, а вычисляются заново. Мемоизация — сохранение результатов выполнения функций для предотвращения повторных вычислений. Перед вызовом функции проверяется, вызывалась ли функция ранее: если не вызывалась, функция вызывается и результат её выполнения сохраняется; если вызывалась, используется сохранённый результат. Классическим примером для иллюстрации является функция, вычисляющая последовательность чисел Фибоначчи:

function fibonacci(n) {

if (n === 0 || n === 1)

return n;

return fibonacci(n - 1) + fibonacci(n - 2);

}

Для больших чисел n количество вызовов функции растёт очень быстро. Уже для n=50 это порядка 40 миллиардов вызовов. Используя идею мемоизации, то есть кеширования промежуточного результата, можно добиться уменьшения количества вызовов для n=50 до всего лишь 99:

var fibonacci = (function() {

var memo = {};

function f(n) {

var value;

if (n in memo) {

value = memo[n];

}

else {

if (n === 0 || n === 1)

value = n;

else

value = f(n - 1) + f(n - 2);

memo[n] = value;

}

return value;

}

return f;

})();

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]