26

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

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

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

何か助けはありますか?

4

8 に答える 8

35

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
于 2015-04-15T13:12:05.030 に答える
24

If you're happy with it being a Float32Array or a subclass of Float32Array and they'll be from the same realm (loosely, window) as the code you're checking, see Anton's answer using instanceof.

If you need to know that it's specifically a Float32Array and not a subclass (and its from the same realm), you could use yourObject.constructor === Float32Array:

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

Live example:

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

But note that will fail if the object originates in a different realm (like another frame), because different environments have different Float32Array constructors (even though they do the same thing).

If you need to support cases where constructor won't work, you can use the Object.prototype.toString.call(yourObject) trick. That returns a useful string for all of the JavaScript built-in types ([object Array], [object Date], etc.) Per specification, Object.prototype.toString when applied to a typed array must return the string in the format "[object TypedArrayNameHere]".

So:

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

Live example:

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()) + "\"");
}

Note that it's possible to create objects that lie about their type, making Object.prototype.toString return the same thing it would return for (say) 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));

于 2013-03-06T15:52:01.453 に答える
14

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

if (yourObject instanceof Float32Array) {
    // your code here
}
于 2013-08-30T10:02:38.167 に答える