.apply()
関数を指定したthis
値と、
配列として提供された引数(arguments
)(または配列風のオブジェクト)で呼び出します。
注意: この関数の文法はcall()とほぼ同じです。 根本的な違いは、call()が引数のリストを受け入れるのに対し、apply()は単一の引数の配列のみを受け取るところです。
文法
fun.apply(thisArg, [argsArray])
引数 | 説明 |
---|---|
thisArg |
fun (関数)の呼び出しに提供されるthis 値を指定します。
このメソッドによって参照されるのは実際の値では無いかもしれないことに注意してください。
もし、メソッドが非strictモードのコード内の関数である場合、
null とundefined はグローバルオブジェクトに置き換えられ、
プリミティブ値はボックス化されます。
|
argsArray |
fun に呼び出される引数として、配列風のオブジェクトを指定します。
関数へ提供する引数が無ければ、null またはundefined を指定します。
ECMAScript 5からは、これらの引数は配列の代わりに、一般的な配列風のオブジェクトにすることが可能になりました。
詳細については、後述する「ブラウザ互換性」を参照してください。
|
説明
このメソッドにより、既存の関数を呼び出す際に、異なるthis
オブジェクトを割り当てることが可能になります。
通常、this
は、呼び出しをしたオブジェクト自体を参照します。
apply
を使用すると、それを書くだけで、
新しいオブジェクトに対してそのメソッドを書き直す必要無く、
別のオブジェクトを引き継ぐことが可能になります。
apply
は、引数にサポートされる型を除き、
call()に非常に似ています。
引数の名前を設定する代わりに、引数の配列を使用することが出来ます。
下記のように、applyでは配列のリテラル、またはArrayオブジェクトを使用することが可能です。
// 配列のリテラル
fun.apply(this, ['eat', 'bananas'])
// Arrayオブジェクト
fun.apply(this, new Array('eat', 'bananas'))
argsArray
パラメーターに、argumentsを使用することも可能です。
argumentsは関数のローカル変数であり、
呼び出されたオブジェクトで、未指定の引数の全てを使用することが可能です。
そのため、applyメソッドを使用する際に、必ずしも呼び出されるオブジェクト側の引数を把握している必要はありません。
呼び出されるオブジェクトへ全ての引数を渡すのに、arguments
を使用することが可能ですが、
呼び出されたオブジェクト側は、引数を処理する責任を負う必要があります。(翻訳に自信なし)
ECMAScript 5thエディションからは、配列風のオブジェクトも使用可能で、
そのオブジェクトはlength
プロパティと、範囲([0...length])の数値プロパティを持つ必要があります。
例えば、NodeListや、下記のようなカスタムオブジェクトを使用することが出来ます。
{'length': 2, '0': 'eat', '1': 'bananas'}
注意: Chrome 14、Enternet Explorer 9をなどのブラウザでは、 配列風のオブジェクトを受け付けていないため、例外がスローされます。
例
applyを使用したチェーンコンストラクタ
Javaのように、オブジェクトのチェーンコンストラクタにapply
を使用することが可能です。
下記の例では、引数のリストの代わりに、
コンストラクタで配列風のオブジェクトを使用出来るようにしてくれる、
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, "Hello world!", false];
var myInstance = MyConstructor.construct(myArray);
// "Hello world!"を表示
alert(myInstance.property1);
// "true"を表示
alert(myInstance instanceof MyConstructor);
// "MyConstructor"を表示
alert(myInstance.constructor);
注意: この非ネイティブのFunction.cnstruct
メソッドは、
ネイティブのコンストラクタ(例えば、Date等)では動作しません。
こういったケースでは、Function.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];
/* Math.min/Math.max、applyを使用 */
/* 下記は、Math.max(numbers[0], numbers[1]...)、
または、Math.max(5, 6, ...)の処理に相当 */
var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);
/* vs 単純なループアルゴリズム */
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エンジンの引数のlength上限を超えてしまう恐れがあることに注意してください。
制限は指定されていため、多すぎる引数(おそらく数万)の関数への適用は、
JavaScriptエンジンごとに異なります。
(JavaScriptCoreは65536の引数上限がハードコードされています)
JavaScriptエンジンによっては、例外をスローします。 より悪いケースでは、実際にapplyの関数へ渡された引数の数が、上限としている別の数に差し替わってしまいます。 (後者の例について説明するために、引数の上限が4つのエンジンがあるとして、[もちろん実際は断然大きい数です]、 上記の例に当てはめると、完全な配列ではなくapplyには5,6,2,3の引数(7が欠損)が渡されてしまいます。) もし、配列の要素数が数万になりそうな場合は、 下記のように前述した例の両方の処理を取り入れて 関数へのapplyを、分割した配列に対して一度に行ってみてください。
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を使用した"モンキーパッチ"
apply
は、組み込み関数やJSライブラリに対してモンキーパッチを当てる最善の方法と言えます。
下記のようにsomeobject.foo
関数をハックして、関数を変更することが可能です。
//元の関数への参照を保持
var originalfoo = someobject.foo;
//someobject.fooを変更
someobject.foo = function() {
//関数が呼ばれる前に、何らかの処理を実行
console.log(arguments);
//従来の処理を行うものとして、元の関数を呼び出し
originalfoo.apply(this,arguments);
//関数が呼ばれた後に、何らかの処理を実行
}
このメソッドは、イベントまたは様々な.on([event])のようなAPIを持たないインターフェースをデバッグしたい際に特に便利です。 (event - デベロッパーツールのインスペクタが利用できるイベント)(翻訳に自信なし)
仕様
ブラウザ互換性
機能 | Chrome | Firefox (Gecko) |
IE | Opera | Safari |
---|---|---|---|---|---|
基本 | ◯ | ◯ | ◯ | ◯ | ◯ |
ES 5.1 引数として 配列風オブジェクト 指定可 |
? | 4.0 (2.0) | ? | ? | ? |
機能 | Android | Chrome for Android |
Firefox Mobile |
IE Mobile |
Opera Mobile |
Safari Mobile |
---|---|---|---|---|---|---|
基本 | ◯ | ◯ | ◯ | ◯ | ◯ | ◯ |
ES 5.1 引数として 配列風オブジェクト 指定可 |
? | ? | 4.0 (2.0) | ? | ? | ? |
関連項目
© 2017 Mozilla Contributors
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
このページは、ページトップのURL先のMozilla Developer Network(以下、MDN)のコンテンツを翻訳した内容を基に構成されています。 構成について異なる点も含まれますので、下記の項目を確認し、必要に応じて元のコンテンツをご確認ください。 もし、誤訳などの間違いを見つけましたら、 @tomofまで教えていただければ幸いです。
- 特定のブラウザに特化しすぎている情報やあまりにも古い情報、 または試験的に導入されているようなAPIや機能については、省略していることがあります。
- 例やデモについて、実際にページ内で動作させる関係で一部ソースコードを変更している場合や、 その例で使用しているコンテンツの単語や文章などを日本人向けに変更しいてる場合があります。
- MDNの更新頻度が高いため、元のコンテンツと比べ情報が古くなっている可能性があります。
- "訳注:"などの断わりを入れた上で、日本人向けの情報の追記を行っている事があります。