★ wanayoo — archive 1999 https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/applyNouvelle recherche | Portail wanayoo
mozilla
Your Search Results

    Function.prototype.apply()

    Сводка

    Метод apply() вызывает функцию с указанным значением this и аргументами, предоставленными в виде массива (либо массивоподобного объекта).

    Примечание: хотя синтаксис этой функции практически полностью идентичен функции call(), фундаментальное различие между ними заключается в том, что функция call() принимает список аргументов, в то время, как функция apply() принимает простой массив с аргументами.

    Синтаксис

    fun.apply(thisArg[, argsArray])

    Параметры

    thisArg
    Значение this, предоставляемое для вызова функции fun. Обратите внимание, что this может не быть реальным значением, видимым этим методом: если метод является функцией в нестрогом режиме, значения null и undefined будут заменены глобальным объектом, а примитивные значения будут упакованы в объекты.
    argsArray
    Массивоподобный объект, определяющий аргументы, с которыми функция fun должна быть вызвана, либо null или undefined, если в функцию не надо передавать аргументы. Начиная с ECMAScript 5 эти аргументы могут быть обобщёнными массивоподобными объектами, а не только массивом. Смотрите ниже информацию по совместимости с браузерами.

    Описание

    Вы можете присваивать различные объекты this при вызове существующей функции. this ссылается на текущий объект, вызвавший объект. С помощью apply вы можете написать метод один раз, а затем наследовать его в других объектах, без необходимости переписывать метод для каждого нового объекта.

    Метод apply очень похож на метод call(), за исключением поддерживаемого типа аргументов. Вы можете использовать массив аргументов вместо набора именованных параметров. Вместе с apply вы можете использовать литерал массива, например, fun.apply(this, ['есть', 'бананы']), либо объект Array, например, fun.apply(this, new Array('есть', 'бананы')).

    Также вы можете использовать в качестве параметра argsArray псевдомассив arguments. arguments является локальной переменной функции. Он может использоваться для всех неопределённых аргументов вызываемого объекта. Таким образом, вы не обязаны знать, сколько и какие аргументы требует вызываемый объект при использовании метода apply. Вы можете использовать псевдомассив arguments для передачи всех аргументов в вызываемый объект. Вызываемый объект самостоятельно разберётся с обработкой аргументов.

    Начиная с 5-го издания ECMAScript, вы также можете использовать любой вид массивоподобного объекта, что на практике означает, что он должен иметь свойство length и целочисленные свойства в диапазоне [0...length). В качестве примера, теперь вы можете использовать NodeList или свой собственный объект вида { 'length': 2, '0': 'есть', '1': 'бананы' }.

    Примечание: Большинство браузеров, включая Chrome 14 и Internet Explorer 9, всё ещё не принимают массивоподобные объекты и будут выбрасывать исключение.

    Примеры

    Пример: использование apply для связи конструкторов объекта в цепочку

    Вы можете использовать метод apply для объединения в цепочку конструкторов объекта, как в Java. В следующем примере мы создадим в объекте Function глобальный метод construct, который позволит нам импользовать массивоподобные объекты с конструктором вместо списка аргументов.

    Function.prototype.construct = function(aArgs) {
      var fConstructor = this, fNewConstr = function() { fConstructor.apply(this, aArgs); };
      fNewConstr.prototype = fConstructor.prototype;
      return new fNewConstr();
    };
    

    Пример использования:

    function MyConstructor() {
      for (var nProp = 0; nProp < arguments.length; nProp++) {
        this['property' + nProp] = arguments[nProp];
      }
    }
    
    var myArray = [4, 'Привет, мир!', false];
    var myInstance = MyConstructor.construct(myArray);
    
    alert(myInstance.property1);                // выведет 'Привет, мир!'
    alert(myInstance instanceof MyConstructor); // выведет 'true'
    alert(myInstance.constructor);              // выведет 'MyConstructor'
    

    Примечание: этот неродной метод Function.construct не будет работать с некоторыми родными конструкторами (вроде конструктора Date, к примеру). В этих случаях вы можете использовать метод Function.prototype.bind (например, представьте что вы имеете следующий массив, который можно использовать с конструктором Date: [2012, 11, 4]; в этом случае вы напишите что-то вроде: new (Function.prototype.bind.apply(Date, [null].concat([2012, 11, 4])))() — так или иначе, это не самый изящный способ и, вероятно, его не стоит использовать в рабочем окружении).

    Пример: использование apply и встроенных функций

    Умное использование метода apply позволяет вам использовать встроенные функции для некоторых задач, для которых в противном случае пришлось бы писать цикл по массиву значений. В качестве примера давайте используем Math.max/Math.min для нахождения максимального/минимального значения в массиве.

    /* мин/макс числа в массиве */
    var numbers = [5, 6, 2, 3, 7];
    
    /* используем apply к Math.min/Math.max */
    var max = Math.max.apply(null, numbers); /* Это эквивалентно Math.max(numbers[0], ...)
                                                или Math.max(5, 6, ...) */
    var min = Math.min.apply(null, numbers);
    
    /* сравним с простым алгоритмом с циклом */
    max = -Infinity, min = +Infinity;
    
    for (var i = 0; i < numbers.length; i++) {
      if (numbers[i] > max) {
        max = numbers[i];
      }
      if (numbers[i] < min) {
        min = numbers[i];
      }
    }
    

    Но будьте осторожны: при использовании метода apply таким образом вы рискуете выйти за пределы ограничения на количество аргументов в движке JavaScript. Последствия применения функции с очень большим количеством аргументов (думается, больше десяти тысяч аргументов) различаются от движка к движку (JavaScriptCore имеет жёстко зашитое ограничение на количество аргументов в 65536), поскольку этот предел (на самом деле, это природа поведения любого чрезвычайно огромного стека) не определён. Некоторые движки будут выкидывать исключение. Хуже того, другие просто отбрасывают реально переданные функции аргументы сверх лимита. (Для иллюстрации последнего случая: если такой движок имеет ограничение в четыре элемента [реальное ограничение, конечно же, гораздо выше], это выглядело бы так, как если бы в примере выше в метод apply были переданы аргументы 5, 6, 2, 3, а не весь массив.) Если ваш масив значений может вырасти до десятков тысяч, используйте смешанный подход: применяйте вашу функцию к порциям массива:

    function minOfArray(arr) {
      var min = Infinity;
      var QUANTUM = 32768;
    
      for (var i = 0, len = arr.length; i < len; i += QUANTUM) {
        var submin = Math.min.apply(null, arr.slice(i, Math.min(i + QUANTUM, len)));
        min = Math.min(submin, min);
      }
    
      return min;
    }
    
    var min = minOfArray([5, 6, 2, 3, 7]);
    

    Пример: использование apply в «monkey-патчинге»

    Метод apply может быть лучшим вариантом для «monkey-патчинга» встроенных в Firefox функций, либо JS библиотек. Пусть у вас есть функция someobject.foo, вы можете изменить её таким немного хакерским способом:

    var originalfoo = someobject.foo;
    someobject.foo = function() {
      // Делаем что-то до вызова функции
      console.log(arguments);
      // Вызываем функцию так, как будто бы она была вызвана обычным образом:
      originalfoo.apply(this, arguments);
      // Делаем что-то после вызова функции.
    }
    

    Этот метод особенно удобен, когда вам нужно отладить события, либо интерфейс с чем-то, что не имеет API, вроде различных событий .on([event]..., например, тех что используются в Инспекторе инструментов разработчика).

    Спецификации

    Спецификация Статус Комментарии
    ECMAScript 3-е издание. Стандарт Изначальное определение. Реализована в JavaScript 1.3.
    ECMAScript 5.1 (ECMA-262)
    Определение 'Function.prototype.apply' в этой спецификации.
    Стандарт  
    ECMAScript 6 (ECMA-262)
    Определение 'Function.prototype.apply' в этой спецификации.
    Черновик  

    Совместимость с браузерами

    Help improve compatibility tables by filling out this 11 question survey.
    Возможность Chrome Firefox (Gecko) Internet Explorer Opera Safari
    Базовая поддержка (Да) (Да) (Да) (Да) (Да)
    Обобщённые массивоподобные объекты ES 5.1, вроде arguments ? 4.0 (2.0) ? ? ?
    Возможность Android Chrome для Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
    Базовая поддержка (Да) (Да) (Да) (Да) (Да) (Да)
    Обобщённые массивоподобные объекты ES 5.1, вроде arguments ? ? 4.0 (2.0) ? ? ?

    Смотрите также

    Метки документа и участники

    Метки: 
    На данную страницу внесли свой вклад: Mingun
    Обновлялась последний раз: Mingun,