1

前に、backbone.js の_.isArray(arr)関数が true を返す理由を尋ねました。

var a = [];
    a.something = "test";

私はそれが に変わることを期待していたので[object Object](それがあなたがしたときに作成されるオブジェクトを参照する正しい方法であるかどうかはわかりませんがvar o = {}、 key: value ペアを使用できるオブジェクトのタイプについて話しているのです.そのオブジェクトを参照する方法についての洞察は大歓迎です。

aデータ型を変更するのではなく、プロパティを追加するだけだという回答を受け取りましたsomething。コンソールで a.something = "test" が表示されていることがわかりますが、これはどこに保存されていますか? それは配列のプロトタイプにありますか?(そうではないと確信しています)。しかし、単純に「プロパティを追加する」とはどういう意味でしょうか?

var a = "";
a.asdf = "test";
a.zxcv = "test1";

文字列はオブジェクトではないため、同様にプロパティを返しませんが、関数はオブジェクトである必要がありますが、

var a = function(){};

    a.asdf = "test";
    a.zxcv = "test1";

    console.log(a);

返すだけ

function (){

} 

(文字列のように見えます...)なぜできないのかわからないvar a = new Function()(見たことがないのに); 上記と同じものを返します。また、jslint はそれが eval だと言っています。どうして..?

「オブジェクトにプロパティを追加する」ことの意味と、これらのプロパティが「移動」する場所、およびオブジェクトの種類によって動作が異なる理由を理解しようとしています。

4

2 に答える 2

3

undefinedJavaScript には、 、 、 など、いくつかのプリミティブ型がnumberありstringます。Sもありますobject。すべてのオブジェクトにはプロパティがあります。

すべての小文字 o オブジェクトは、コンストラクターから作成されました。オブジェクト リテラル表記の場合、コンストラクターは暗黙の でしたObject。配列もオブジェクトですが、コンストラクターで作成されるのではなく、Objectコンストラクターで作成されますArray。関数もFunctionコンストラクタを持つオブジェクトです。

配列

配列を見ると、番号付きの要素を持っていると考える可能性があります。0、1、2 など。実際には、配列は別のオブジェクトにすぎませんが、アルファベットのプロパティ名を使用するのではなく、数値のプロパティ名を使用.し、要素へのアクセスには使用しません。

実際には、異なる種類のオブジェクトを使用する場合よりも高速になるように、ブラウザーによって配列が最適化されていますが、そのような最適化でもここで説明するセマンティクスは保持されます。

ボクシング

文字列の奇妙な動作は、文字列がオブジェクトではないためですがsomeString.property = value、エラーにならない風変わりなボックス化動作がいくつかあります。プロパティとメソッド自体を持つことができるのはオブジェクトだけです。しかし、それが間違いではないことは誰もが知ってsomeNumber.toString()います。何が起きているの?

場合によっては、プリミティブをオブジェクトであるかのように使用しようとすると、そのプリミティブがオブジェクトにボックス化されます。たとえば、 を呼び出すと、プリミティブ番号とは異なるsomeNumber.toString()、コンストラクターを持つオブジェクトが作成されます。Number次にtoString、通常の方法で検索しthis、オブジェクトに設定して実行します。

文字列にプロパティを設定するとString、その操作のために暗黙的に -constructor オブジェクトに変換されました。Stringオブジェクトのプロパティを問題なく設定しました。ボクシングが一時的なものだっただけです。ボックス化は、プリミティブ文字列を保持する変数では持続しません。

関数オブジェクト

めったに を使用しないのは事実ですnew Functionが、使用すると、まさにそのように聞こえます: 新しい関数を作成します。文字列を渡すことができ、それが関数の本体になります。文字列本体を使用して新しい関数を作成し、それを呼び出す場合、それはevaling コードからそれほど遠くありません。そのため、JSLint はそれを としてマークしますeval

オブジェクトをコンソールに記録すると、開発者ツールは通常、オブジェクトの最も重要な部分であるため、プロパティを表示します。通常、関数にはカスタム プロパティが割り当てられないため、開発者ツールは、通常は関数の引数と本体のみを表示するプレーンな文字列表現を使用します。関数の文字列表現は、プロパティを表示しないという点でそれほど珍しいことではありません —toString単純なものObjectは単に を返し[object Object]ます。

プロトタイプチェーン

確かに、この情報は多くのことを明確にしていますが、まだこれを説明していません:

console.log(new Array() instanceof Object);  // => true

なに?配列のコンストラクターはArrayではなくObject! これは、プロトタイプチェーンと呼ばれるものによるものです。それは継承を制御するものです。

すべてのオブジェクトには、 と呼ばれる内部プロパティがあります[[Prototype]]。これにアクセスするための標準的な方法はありませんが、多くのブラウザには標準外の__proto__プロパティでアクセスできます。newオブジェクトの作成に使用すると、オブジェクトの作成に使用した関数[[Prototype]]のプロパティに設定されます。prototype

fooのコンストラクタを持つオブジェクトがあるとしましょうFoo。プロパティにアクセスするfoo.barと、最初に 自身のプロパティが検索さbarfooます。そこに見つからないか未定義の場合は、 の独自のプロパティを検索しますbar。そこに見つからない場合は、 に到達するまで、のを何度も検索します。これは、継承を可能にする機能です。foo[[Prototype]]barfoo[[Prototype]][[Prototype]]null [[Prototype]]

オブジェクトがインスタンスであるかどうかを判断するために、isinstanceはプロトタイプ チェーンを調べて、 のいずれかが関数[[Prototype]]の と一致するかどうかを確認prototypeします。配列のプロトタイプチェーンをトラバースすると、Arrayのプロトタイプ、Objectのプロトタイプ、そしてnull. したがって、 でisinstance降伏truenew Array() instanceof Objectます。

参考文献

注釈付きの ECMAScript 5 仕様に興味があるかもしれません。これは言語を定義し、もちろん使用される特定のアルゴリズムの一部を詳細にカバーしています。それはあなたのためにすべてをレイアウトするわけではありません。いくつかの非常に洞察力のあることは明示的に説明されていませんが、自分でいくつかのビットをつなぎ合わせる必要があります. そのため、自分で実装しようとしない限り、最初から最後まで読むのは避け、気になる動作があればいつでもセクションを参照してください。

于 2013-07-25T05:40:20.943 に答える
0

JavaScript では、配列は 0 から n 個の値までのキーが事前に割り当てられたオブジェクトです。

var x = ['a','b','c','d',234];まったく同じです

var x = {0:'a',1:'b',2:'c',3:'d',4:234,length:5}; すべての配列関数は、このような配列呼び出しで機能しますArray.prototype.sort.push(x,'sdfsd');

Main Object のすべてのメソッド/プロパティは、すべての配列に継承されます。

したがって、数値以外の値を配列に割り当てる場合は、2 つの要素を使用するとします。このように追加されます...

var x =['a','Stack','flow',0];
--added value x.a = 'something';
it really looks like this now
var x = {
    0:'a',
    1:'Stack',
    2:'flow',
    3:'0',
    a:'something'
    }

ただし、js にとってxは依然として配列であり、 xで関数を実行しただけではa は表示されません。のようにアクセスするまでx.a

x.hasOwnProperty('a'); //true

Object.keys(x); //listing all keys in object(array x)
// ["0", "1", "2", "3", "a"] !!!keys function returns an array consisting of all keys in an object.

関数オブジェクトは違います。キーを持つオブジェクトだけではありません。

それらに何かを割り当てることはできますが、機能のみを返します。xa などのプロパティにアクセスできますが、そうしないでください。

概要

すべてがオブジェクトから継承されるObjectため、プロパティとメソッドを持つことができます。

配列は特殊なオブジェクトであり、Arrayからメソッド/プロパティを継承して呼び出されObject、0-n 形式のインデックス付きキーに値を格納します。ただし、継承により追加のプロパティとメソッドを持つことができますが、配列のメソッドまたはプロパティには表示されません。

function object関数は、継承元のオブジェクトであるObjectため、関数 (functionObjects) は両方のプロパティを持ちます。関数には、プロトタイプや引数などの追加のプロパティもあります。

これを書くとき:...

var x = new function anonymous/named (){} 3 つのことが起こります: 1. x = {}; 2. 関数が実行されます... this.p = etcc がある場合... x はそれを取得し、x は x= {p:'etc'} になります 3. x. proto = function.prototype

次に、xでプロパティまたはメソッドを検索し、そこに見つからない場合、jsはプロトに何かがあるかどうかを調べ、関数のプロトタイプオブジェクトを参照してそこに移動し、そこで検索します。これが、Javascript でクラスを作成する方法です。

于 2013-07-25T05:42:03.497 に答える