Array.prototype.forEach() と Array.forEach()の違い


`Array.prototype.forEach()`と`Array.forEach()`は何が違うのでしょうか？

  * `Array.forEach()`と書いたら、内部で`Array.prototype.forEach()`が呼ばれるので、わざわざ`Array.prototype.forEach()`と書く必要はない？
  * それとも`Array.prototype.forEach()`と書くと、`Array.forEach()`では出来ない何かの処理ができるのでしょうか？

* * *

回答ありがとうございました。  
質問するに辺り、最初に疑問に思った点を追記します。  
・下記は何が違うのでしょうか？  
[Array.forEach](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)  
[Array.prototype.forEach()](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)

基本はArray.prototype.forEach()だと思うのですが、  
Array.forEachは、Array.prototype.forEach.call()の汎用的な簡易表記ということなのでしょうか？  
Mozilla(Firefox)だけの書き方？




> ・下記は何が違うのでしょうか？  
>
> [Array.forEach](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)  
>  [Array.prototype.forEach()](https://developer.mozilla.org/en-
> US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)

前者のページ右上に表示されている「言語」から「English
(US)」を選択していただくとわかるかと思いますが、その二つは同じ対象について書かれたものです。

確かにページタイトルでは `Array.forEach` となっているのですが、構文は次のように書かれています。

> _array_.forEach( _callback_ [, _thisObject_ ]);

ここで斜体になっている `array` は任意の配列ですから、 `Array.forEach(...)` として使うことはありません。

>
> このリファレンスには、文書中の主題の適切なもしくは共通な利用法を具体的に説明するための構文の説明の部分があります。これらの部分では、文字通りそのままであることを表すすべてのテキストリテラルは
> 3 点リーダを除いてイタリックにはなっていません。イタリックの単語はユーザ定義の名前や 文 (statements) を表します。
>
> 引用元: <https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference>

prototype の話はなかなか複雑なのでここでは避けますが、 `Array.prototype.forEach` に定義されている関数が、配列
`hoge` に対して `hoge.forEach(...)` として呼び出せる、というようなものです。

* * *

一方、処理系やブラウザによっては、字のごとく `Array.forEach`
が存在する場合もあります。その一例がFirefoxでの[Arrayジェネリックメソッド](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array%23Array_generic_methods#Array_generic_methods)です。

`Array.prototype`
以下に定義されているメソッドは、実際には対象に対して決まりきった操作をするものですから、配列と似た動きをするオブジェクトであれば使えることがあります。  
※これ自体はECMAScriptの言語仕様でも `The forEach function is intentionally generic`
のように[言及されています](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18)。

そのため `Array.prototype.forEach.call()`
などとして強引に他のオブジェクトに対して実行するというテクがあるのですが、Mozillaはこれの代替として `Array.forEach`
などを用意することにした、ということのようです。

この `Array.forEach` は「いわゆるJavascript」の標準規格である
[ECMAScript](http://ja.wikipedia.org/wiki/ECMAScript)
には含まれていないため、互換性は低いと言えるでしょう。




> `Array.forEach()` と書いたら、内部で `Array.prototype.forEach()` が呼ばれるので、わざわざ
> `Array.prototype.forEach()` と書く必要はない？

いいえ。[ECMAScriptの定義](http://www.ecma-
international.org/ecma-262/5.1/#sec-15.4.4.18)の範囲では `Array.forEach`
は未定義(`undefined`)なので `Array.forEach()` を実行するとエラーになる場合があります。仮にあるプロジェクト/環境で
`Array.forEach()` が実行可能なのだとすれば、それは環境や利用しているライブラリなどが独自に `Array.forEach =
Array.prototype.forEach;` のようなことを事前に行っているために、可能になっているのでしょう(例: Firefox)。

一般に関数 `A()` に対して定義された `A.prototype.foo` は直接利用するか、以下のサンプルコードで示すように `new A()`
したインスタンスから使用でき、`A.foo` という参照は `A.prototype.foo` には転送されません。

[code]

    function A() {}
    A.prototype.foo = function() {
      console.log('foo called');
    }
    
    var a = new A();
    a.foo() // 呼べる!
    
    A.foo() // 呼べない (´・ω・`)
    
[/code]

> それとも`Array.prototype.forEach()`と書くと、`Array.forEach()`では出来ない何かの処理ができるのでしょうか？

JavaScript の互換性を考慮するならば `Array.prototype.forEach()` を利用するようにしてください。

* * *

余談ですが、関数の呼び出し引数を示す `arguments` は Array のインスタンスではありません。そのため
`arguments.forEach()` のような使い方はできないので `Array.prototype.forEach.call()`
を使って以下のようにする必要があります。

[code]

    function bar() {
      Array.prototype.forEach.call(arguments, function(n) {
        console.log(n);
      });
    }
    
    bar(1, 2, 3);
    bar('a', 'b', 'c');
    
[/code]

Mozilla(Firefox) ではコレを無駄であると考え、`Array.forEach()` という _汎用的な簡易表記を導入し_ ているようです。
([引用元](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array%23Array_generic_methods#Array_generic_methods))

