6921


`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)だけの書き方？


CC BY-SA 3.0
2015-02-21T01:41:29.960
6848
2016-10-20T08:47:47.667
2015-02-22T04:04:33.700
7886
7886
question
javascript
Array.prototype.forEach() と Array.forEach()の違い


> `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))


CC BY-SA 3.0
2015-02-21T03:06:25.030
6851
2015-02-21T08:55:17.840
2015-02-21T08:55:17.840
208
208
6848
answer


> ・下記は何が違うのでしょうか？  
>
> [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)
には含まれていないため、互換性は低いと言えるでしょう。


CC BY-SA 3.0
2015-02-22T10:35:42.703
6921
2015-02-22T11:08:01.583
2015-02-22T11:08:01.583
8000
8000
6848
answer


JavaScriptの言語における組み込みの「型」とその「prototypeプロパティー」について  
若干、混乱があるように思いますので以下を見てください。

今回の件でFireFoxとGoogleChromeの両ブラウザの「コンソール」での違いを見てみると  
わかりやすいですよ。実際、以下のコードをそれぞれのコンソールでやってみてください

[FireFox]

[code]

    >typeof Array.forEach;　　　　　　　//"function"　いきなり関数として認識されている！
    >Array.prototype.forEach == Array.forEach; 　　//false んーー別物ですw
    
[/code]

[Chrome]

[code]

    >typeof Array.forEach;　　　　　　//"undefined"　普通（標準で）は、undefinedだよなぁ
    >Array.forEach = clone(Array.prototype.forEach);//cloneは独自ディープコピー関数・定義略
    >typeof Array.forEach;   　　　　//"function"以後FireFox風に(new Array()).forEach(func);可能
    >Array.prototype.forEach = null;  //元メソッドが使われる可能性を排除するため
    >var res=[];　　　　　　　　　　//コピー元のprototypeの方は使えなくするｗ
    >(new Array(1,2,3)).forEach(function(n){ res.push(n*n);})
    >res;　　　　　　　　　　　　//[1,4,9]　型の直の関数が実行された
    
[/code]

ArrayはJavaScriptにおいて組込の型であり  
（クラスという人もいますがJavaScriptにはクラスは無いですから間違いです）  
と同時に「Function型のインスタンス」でもあるので、  
インスタンスベースの言語であるJavaScriptでは  
”インスタンスのArrayに直接APIを追加”できてしまうのです。  
JAVAやC++などクラスベースしか知らない方はココをよく混乱されますが  
JavaScriptでは基本的にはどこにでも、どのような関数でも設置できてしまうということ

質問の「何が違うのでしょうか？」ということへの答えは  
少しイジワルでいえば「関数定義を見てみるまでは判りません」というのが答えになります。  
早い話、どのようにでも（あなた自身でも）「同名」のforEach関数を「どこにでも」  
「どんな中身に変えてでも」設置できるからです。逆に怖いことですが、できてしまうんです、  
どこかのヘボが標準的と捉えられている関数を勝手に変えてるかもしれないからです・・・  
もちろんmozillaさんではちゃんとした関数でしょうが、標準的で一般的な型の  
直接のメソッドを設定してしまうあたりすごい発想！（火のキツネが嫌われる理由ともｗ）

まず１つめは「関数は同名でもなんでも、好きな様に、好きな場所に定義できる」ということです  
（mozillaさんがESにおいて標準的ではないのに、そうしたように）

あと型の直接のメソッドと、その型のprototypeプロパティーのメソッドの「違い」で  
重大な違いは「継承」です。  
型に直接、メソッドを定義すると元の型（Function型インスタンス）では利用できますが  
その設計図を継承した別の（子の）型ではその関数が「見えません」。  
ご存知のようにJavaScriptの継承は「prototypeチェーン」だからです。  
おいてある場所が違えば見えなくて当然ですね。

それから回答などの中でも少し気になったのが型とその型のリテラルです  
今回の場合 Array と [1,2,34]の混乱も少しあったようですが  
型とリテラルの間にどのような動きがあるのかも調べられるといいと思います

またargumentsはArrayのようでArrayでない普通のObject型ですが  
なまじlengthプロパティーだけは持っているのでArryかな？とおもわれがちですので注意

[code]

    (function(){
      alert(arguments instanceof Array);
    })();　　　　　　　　　　　　　　　　　//false
    
    (function(){
      alert(Object.getPrototypeOf(arguments) === Object.prototype);
    })();　　　　　　　　　　　　　　　　//true
    
[/code]

すこし誤表現も含まれてしまったかもしれませんが、基本的に型の理解が伝わればと思います


CC BY-SA 3.0
2015-02-22T14:48:08.863
6931
2016-10-20T08:47:47.667
2016-10-20T08:47:47.667
15185
8477
6848
answer