2013-05-24 7 views
7

JavaScriptでどのオブジェクトがis complicatedであるかを特定し、どのオブジェクトが配列であるかを調べるには、hacky solutionの何かがあります。幸いなことに、それは以下の例の両方で動作するように管理します。Object.createで作成されたオブジェクトがJavaScriptでArrayから継承されているかどうかを確認することはできますか?

Object.prototype.toString.call([]);   // [object Array] 
Object.prototype.toString.call(new Array()); // [object Array] 

グレート、見えない[object Object]!悲しいことに、この方法はこれでも失敗することがあります。

var arr = Object.create(Array.prototype); 
Object.prototype.toString.call(arr);   // [object Object] 

これは不快です。私のarrオブジェクトには配列のすべてのメソッドがあり、配列のように機能し、すべての目的で配列です。しかし、JavaScriptはそれを識別するためのツールを提供していません。

オブジェクトが特定のプロトタイプから継承するかどうかを判断する方法はありますか?私はあなたがそうのようなプロトタイプを反復処理できたとします

function inherits(obj, proto) { 
    while (obj != null) { 
     if (obj == proto) return true; 
     obj = Object.getPrototypeOf(obj); 
    } 
    return false; 
} 

inherits(Object.create(Array.prototype), Array.prototype); // true 

しかし、それはハック少しを感じています。よりクリーンなアプローチはありますか?

+0

私はちょうど好奇心が強い:なぜあなたは今までこのような配列を作成しますか? 'Object.create(Array.prototyp);' 'Object.prototype.toString.call(arr);で確認してください。 – Zim84

+0

@ Zim84:これは単なる例です。実際のアプリケーションでは、決してこれを行うべきではありません。実際のアプリケーションでは、Object.create(Array.prototype)が別の場所で呼び出され、作成されたオブジェクトを別の関数に渡すことがあります –

+0

問題は本当に本当の配列を持たないことです(例えば、一見するとそのように見えるものだけ)。あなたが持っているのは配列のようなもので、真の配列のすべてのメソッドを持っています。 array-likesをチェックしたいのであれば、基本的に 'length'プロパティを持っていて文字列ではないかどうか確認するだけです。それは最高のIMOです。真の配列をチェックするには、 'Object.prototype.toString.call'または' Array.isArray'を使い、 'Array.prototype'のプロトタイプを持つオブジェクトが真の配列であるとは限りません。 –

答えて

2

instanceofさんは。それはすべてあなたのケースのためのtrueを返します。しかし

[] instanceof Array //true 
new Array() instanceof Array //true 
Object.create(Array.prototype) instanceof Array //true 

Object.create(Array.prototype) instanceof Object //also true 

ので注意してください。

+0

instanceof Arrayは、各フレームに独自のArrayコンストラクタがあるため、フレーム間で配列を渡すときに、確実に信頼できる方法を確認できません –

+0

これは、単一フレーム環境またはNodeに対して妥当なソリューションです。マルチフレームの問題を念頭に置いてください。 –

2

ECMAScript 5は、確認のための信頼性の高い方法を提供するjavascriptにArray.isArray()を導入しました。古いブラウザのために、我々はによって(このbookより引用)という修正

function isArray(value) { 
    if (typeof Array.isArray === "function") { 
     return Array.isArray(value); 
    } else { 
     return Object.prototype.toString.call(value) === "[object Array]"; 
    } 
} 

しかし、私はちょうど私たちは(クロームでテスト)Object.createを使用するときに正しく動作しない組み込み関数Array.isArrayを見つけました。

function isArray(value) { 
    if (typeof value === "undefined" || value === null) { 
      return false; 
    } 
    do { 
      if (Object.prototype.toString.call(value) === "[object Array]") { 
       return true; 
      } 
      value= Object.getPrototypeOf(value); 
    } while (value); 

    return false; 
} 

は、それを使用します:私は働く方法を思い付いた

var arr = Object.create(Array.prototype); 
var arr1 = Object.create(Object.create(Array.prototype)); 
var arr2 = new Array(); 
var arr3 = []; 
isArray(arr); 
isArray(arr1); 
isArray(arr2); 
isArray(arr3); 
+1

'Array.isArray'は' Object.prototype.toString.call(arr)== '[オブジェクト配列]'とまったく同じです。このソリューションは、オブジェクトのプロトタイプが配列であるプロトタイプを持つオブジェクトである場合は機能しません。 'var arr = Object.create(Object.create(Array.prototype));' –

+0

@NathanWall:この[book]を見てください(http://books.google.com.vn/books?id=J5RCV8yM7sEC&pg= PA88&LPG = PA88&DQ =ジャバスクリプト+保守+検知+アレイ・ソース= BL&OTS = TDZEDzhWJm&SIG = I92iJt7mAz8rEdHteDFAmCSqLzI&HL = VI&SA = X&EI = XHShUZnkLY6diAerxICgCg&VED = 0CDEQ6AEwAQ#V = 1ページ分&Q =保守%20javascript%20detecting%20array&F =偽) –

+0

@NathanWall:更新された答えをチェックしてください。ありがとう。 –

0

どのようにコンストラクタをチェックするでしょうか?

function inherits(obj, proto) { 
    return obj.constructor === proto.constructor; 
} 

inherits(Object.create(Array.prototype), Array.prototype); // true 
2

アレイから継承する際の問題の決定的な解説については、http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/を参照してください。

とにかく、あなたはisPrototypeOfを使用して確認することができます

var sort_of_an_array = Object.create(Array.prototype); 

を行っている最も単純なケースで:

Array.prototype.isPrototypeOf(sort_of_an_array) 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isPrototypeOfを参照してください。

0

それは配列のように機能し、すべての目的のために、それが何の自動更新length性を有していないアレイ

号です。 this articleを参照してください。Arrayをサブクラス化することは全く不可能です。

オブジェクトが特定のプロトタイプを継承するかどうかを判断する方法はありますか?私はプロトタイプを反復することができると思うが、それは少しハッキリ感じる。

それはそれを行う方法です。自己書かれた機能よりもクリーンなアプローチを使用することですinstanceof operator

arr instanceof Array; // true 
関連する問題