web-dev-qa-db-ja.com

変数がJavaScriptで型付き配列であるかどうかを確認するにはどうすればよいですか?

私はゲームに取り組んでおり、数学型には型付き配列(Float32Arrays)を多用しています。 JSONからgamestateを保存してロードします。 JSON stringify出力の例は、そのような配列(Chromeの場合)の場合です。

"{"0":0,"1":0,"2":0,"length":3,"byteLength":12,"byteOffset":0,"buffer":{"byteLength":12}}"

これはスペースを浪費し、それらをオブジェクトとしてロードする原因となり、不便です。理想的には、stringify'replacer '関数を使用して、変数が型付き配列であるかどうかをテストし、その場合はそれをbog標準配列に変換できます。残念ながら、変数が型付き配列であるかどうかを確実にテストする方法がわかりません。

何か助けはありますか?

19
AGD

Float32ArrayまたはFloat32Arrayのサブクラスであることに満足している場合、それらは同じからのものになります- レルム(大まかに、ウィンドウ)チェックしているコードとして instanceofを使用したAntonの回答を参照

それが具体的にFloat32Arrayであり、サブクラスではない(そして同じレルムからのもの)ことを知る必要がある場合は、yourObject.constructor === Float32Arrayを使用できます:

if (yourObject.constructor === Float32Array) {
     // It's a Float32Array
}

実例:

if (typeof Float32Array === "undefined") {
  console.log("This browser doesn't support Float32Array");
} else {
  var array = new Float32Array(10);
  console.log(array.constructor === Float32Array); // true
}

ただし、オブジェクトが別のレルム(別のフレームなど)で作成されている場合は失敗することに注意してください。これは、環境によってFloat32Arrayコンストラクターが異なるためです(同じことを行う場合でも)。

constructorが機能しない場合をサポートする必要がある場合は、Object.prototype.toString.call(yourObject)トリックを使用できます。これは、すべてのJavaScript組み込み型([object Array][object Date]など)に役立つ文字列を返します 仕様ごとObject.prototype.toStringを型付き配列に適用すると、文字列を"[object TypedArrayNameHere]"の形式で返す必要があります。

そう:

if (Object.prototype.toString.call(yourObject) === "[object Float32Array]") {
     // It's a Float32Array
}

実例:

if (typeof Float32Array === "undefined") {
  console.log("This browser doesn't support Float32Array");
} else {
  console.log("Object.prototype.toString.call(new Float32Array()) returns: \"" +
    Object.prototype.toString.call(new Float32Array()) + "\"");
}

タイプに依存するオブジェクトを作成して、Object.prototype.toStringが(たとえば)Float32Arrayに対して返すのと同じものを返すようにすることが可能であることに注意してください。

const real = new Float32Array();
const fake = {
  get [Symbol.toStringTag]() {
    return "Float32Array";
  }
};
const realString = Object.prototype.toString.call(real);
const fakeString = Object.prototype.toString.call(fake);
console.log(realString);
console.log(fakeString);
console.log(realString === realString);

// You can also create a class that returns objects that lie:
class Foo {
  get [Symbol.toStringTag]() {
    return "Float32Array";
  }
}
const fake2 = new Foo();
console.log(Object.prototype.toString.call(fake2));
14
T.J. Crowder

ArrayBuffer.isViewあなたを助けるべきです。

var data = [0,1,2]
var dataBuffer = new ArrayBuffer( data )
var dataBufferView = new Float32Array( data )

ArrayBuffer.isView(data) //false
ArrayBuffer.isView(dataBuffer) //false
ArrayBuffer.isView(dataBufferView) //true
dataBuffer instanceof ArrayBuffer //true
22
Greg Tatum

yourObject instanceof Float32Array構文を使用することもできます。オブジェクトがFloat32Arrayのインスタンスである場合はtrueを返し、それ以外の場合はfalseを返します。

if (yourObject instanceof Float32Array) {
    // your code here
}
13
Anton

誰もこれを下に持っていないことに驚いています。これは、ほとんどの場合、型付き配列があるかどうかを判断するために機能するはずです。

function isTypedArray(a) { return !!(a.buffer instanceof ArrayBuffer && a.BYTES_PER_ELEMENT); }

var a = [];
console.log(isTypedArray(a)); // (false);
var a = new Float32Array(3);
console.log(isTypedArray(a)); // (true);
var dataView = new DataView(a.buffer);
console.log(isTypedArray(dataView)); // (false);
console.log(isTypedArray(Float32Array)); // (false);

もちろん、これは「ダックタイピング」であり、a instanceof Float32Arrayまたは同様のものは、特定のタイプを確実に知るための最良の方法です。

3
James Wilkins

ArrayBufferViewおよびDataViewタイプのいずれかをキャッチするより一般的なテストが必要な場合は、次を使用できます。

if (Object.prototype.toString.call(yourObject.buffer) === "[object ArrayBuffer]") {
     // It's either an ArrayBufferView or a DataView
}
2
visibleman

型指定された配列はすべてArrayBufferから継承されます。このタイプにはbyteLengthプロパティが含まれているため、このプロパティが使用可能かどうかを簡単に確認してください。

function isTypedArray(obj)
{
    return !!obj && obj.byteLength !== undefined;
}
1
Martin Wantke