2013-08-02 1 views
25

ゲームをプログラミングしながら、私は1日間違えてこの出くわし:JavaScriptを使用すると、配列と関数を1つの変数に格納できるのはなぜですか?

var foo = function() { alert("Hello, World!"); } 

foo[0] = "Zero"; 
foo[1] = "One"; 
foo[2] = "Two"; 
foo[3] = "Three"; 

foo(); // Alerts "Hello, World!" 
alert(foo[2]); // Alerts "Two" 

なぜJavaScriptは、あなたがこれをやらせるのか?これは不具合ですか?

+5

あなたの質問は、あなたの質問に対する私の最初の反応は、基本的に*なぜそうではないのか*私は*なぜ*質問するかもしれません。 –

+0

配列の場合と同じように、関数上で同じプロパティやメソッドを呼び出さないためでしょうか? – Xynariz

+5

関数はオブジェクトです。オブジェクトはプロパティを持つことができるので、 'foo.bar =" baz "'は合法です。Javascriptには、オブジェクトのプロパティにアクセスする2つの方法があります。ドット表記法とブラケット表記法です。後者を使用しています。 –

答えて

37

ここには配列はありません。たとえば、Array.isArray(foo)はfalseです。

代わりに、異なる値で、[1] 名前付きプロパティ、"1""2"、および"3"を与えています。関数はオブジェクトなので、これは完全に有効です。任意の名前を付けてオブジェクトにいつでもプロパティをアタッチできます。

また、行うことができます:

foo.otherProp = "hi!"; 

alert(foo.otherProp); 

は、[1]:プロパティ名は常にそれらを設定する前に、文字列に変換されていることに注意してください。 foo[{ toString: function() { return "baz"; }] = 5を実行すると、foo["baz"] = 5またはfoo.baz = 5と同じになります。同様に、foo[0] = "whatever"を実行することはfoo["0"] = "whatever"と同じです。

+1

JSは 'foo [0]'を '' 0 ''*(文字列)*に変換していますので' foo [0] 'と' foo ["0"] 'は同じですか、Domenicですか?コンソール上でテストされ、そのように見えます。 – RaphaelDDL

+1

ええ、私はそれについて脚注を追加しました。 – Domenic

+1

@RaphaelDDL:正しい。 –

0

Javascriptのほとんどのもの(関数を含む)はオブジェクトなので、01のような追加のプロパティを与えることができます。

+3

これは当てはまりません: '5'はオブジェクトではありません。試してみましょう: '5.foo =" bar ";警告(5.foo); '。同じことが他のすべてのプリミティブにも当てはまります。何かがオブジェクトであるかどうかの一般的なテストは、 'Object(物)===事物かどうかです。 – Domenic

+0

@Domenic:真実ですが、実際にプリミティブはオブジェクトに昇格されます(例えば '(5).foo =" bar "';小数点のように)、プロパティが追加され、そのオブジェクトが破棄されます。 (これは '' string ".anyMethodHere()'の全般的な理由です)。*という文は広すぎますが、あまりにも広いです。 :-) –

+1

@Domenic @ T.J.Crowderが言ったことに加えて、 '5..foo = 'bar';'を実行することもできます。最初のドットは小数点として解釈され、2番目のドットはプロパティへのアクセスとして解釈されます。 –

4

答えは非常に簡単で、私の娯楽のためには三和論辞で表すことができます。

すべてのオブジェクトは、開発者定義のプロパティーを持つことができます。。
すべての関数はオブジェクトです。
したがって、すべての関数は開発者定義のプロパティを持つことができます。技術的には


ないすべてオブジェクト。 「強化された」オブジェクトは、信頼できないコードによって変更されることはありません。また、JavaScriptランタイムを組み込んだアプリケーションによって提供されるオブジェクトは、これを防ぐために動作をカスタマイズすることができます。しかし、これはエッジケースです。 JavaScriptランタイム内で作成された非硬化オブジェクトは、すべてこの機能を備えている必要があります。ほとんどの場合、これらは変更しようとしているオブジェクトです。

9

なぜJavaScriptは配列と関数を1つの変数に格納できるのですか?

これはありません。関数への参照を変数に格納することができます。

  1. :など"0"のような名前を持つもの、"1"

    あなたがここに遊びに物事のカップルを見ているなど、機能はJavaScriptでファーストクラスのオブジェクトであり、したがって、彼らは性質を持つことができます上で述べたように、関数はオブジェクトなので、プロパティを追加することができます。

  2. プロパティを特別に追加できます。他の言語と同様に事前定義する必要はありません。JavaScriptで

  3. 、あなたはドット表記とリテラル(foo.bar)を使用して、または角カッコと文字列(foo["bar"])を使用してプロパティを参照することができます。

  4. をあなたは括弧表記を使用すると、カッコ内のものそれはすでにないので、[0]が実際に["0"]ある場合。文字列に

をキャストして、はい、その最後が標準arrays in JavaScript aren't really arraysので、あなたは配列を扱っている場合でも、本当です。(最近あります追加この場合、「0」という名前のプロパティに値を代入します。この場合、trueの配列ですが、Arrayはありません。)

+0

配列内の配列への参照を変数に格納することについての文章が削除されました。これは混乱している可能性があり、誤解を招く可能性があるためです。ちょっと気分が悪いと思ったら、ちょうどコメントして、自分でやりましょう。 – Domenic

+1

@Domenic:ありがとう、それはちょうどタイプミス(「配列」、私が「機能」を意味する)でした。 –

+1

これは、このコード部分で起こっているすべてのさまざまなことを素早く分離します。 +1 – Domenic

3

foo[0]この場合、値は「0」という名前のプロパティに割り当てられます。関数はオブジェクトであり、プロパティを追加することができます。同様に

、これら二つはequivilantです:すべての

foo["abc"] 
foo.abc 
0

まず、あなたの質問は、あなたのタイトルとは何の関係もありません。

「なぜJavaScriptは配列と関数を1つの変数に格納するのですか?」という質問に対して、は動的にタイプされた言語であり、好きなものを置くことができます変数では、通訳者は不平を言うことはありません。

質問の本文では、あたかもオブジェクトまたは配列のように、関数の属性を設定することが許可されているのだろうと思います。

まあ、できます。それが言語の定義です。関数に関するメタ情報を追加することは非常に便利です。

はい、JavaScriptはシャープなエッジとポイントビットで覆われているので、注意する必要があります。

+1

'まず、あなたの質問はあなたのタイトルとは関係ありません。 ' - それは私たちには当てはまりますが、OPとしては明らかに明らかではありません。プロパティ)。動的に型定義されたJavaScriptは、OPのタイトルとは関係がありません。変数が関数と配列の両方を保持していると誤って考えていることは明らかです。そして、「まあ、あなただけです。それは言語の定義です.'有用な答えではない – Ian

0

JavaScriptでは、関数はファーストクラスオブジェクトです。

function foo() {} 
var isObject = foo instanceof Object; 
// isObject is true 

などの機能からそれらを返す、引数として渡す、変数に機能を割り当てるとの契約だ

Reference on MDN

0

何誰のは、これまでに述べられていないと、この機能が可能であることです関数に役立つ可能性のある関数と情報を関連付けることができますが、衝突などを引き起こす可能性のある多くのパブリックデータでグローバル空間を汚染することはありません。

もちろんこれは一般的なOOP /プロトタイプの機能ですが、より一般的なオブジェクトのプロパティではなく、関数を直接呼び出せるという利点があります。

関連する問題