26

我正在开发一款游戏,我们广泛使用类型化数组 (Float32Arrays) 作为我们的数学类型。我们从 JSON 保存和加载游戏状态。JSON stringify 输出的一个示例是这样一个数组(在 Chrome 中)是:

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

这会浪费空间并导致它们作为不方便的对象加载。理想情况下,我们可以使用 stringify 'replacer' 函数来测试变量是否是类型化数组,然后在这种情况下将其转换为 bog 标准数组。不幸的是,我不确定如何可靠地测试变量是否是类型化数组。

有什么帮助吗?

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

Float32Array 如果您对它是一个或一个子类感到满意,Float32Array并且它们将来自与您正在检查的代码相同的领域(松散地,窗口),请参阅 Anton 的答案,使用instanceof.

如果您需要知道它具体是 aFloat32Array而不是子类(并且它来自同一个领域),您可以使用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返回与 (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如果您的对象是Float32Arrayandfalse在其他情况下的实例,它会返回。

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

我找到了一个更好的方法,如果你想测试每一个可能的 TypedArray,根据MDN,你可以得到TypedArray构造函数。使用此构造函数,您可以测试某物是否属于其类型:

var x = new Uint32Array();
var TypedArray = Object.getPrototypeOf(Uint8Array);
console.log(x instanceof TypedArray);

您可以将其保存到这样的函数中:

const isTypedArray = (function() {
  const TypedArray = Object.getPrototypeOf(Uint8Array);
  return (obj) => obj instanceof TypedArray;
})();
于 2020-12-23T15:52:16.410 回答
3

我很惊讶没有人在下面得到这个。在大多数情况下,这应该可以确定您是否有类型化数组:

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或者类似的方法是确定特定类型的最佳方式。

于 2017-10-24T04:56:23.600 回答
2

如果您想要一个更通用的测试来捕获您可以使用的任何 ArrayBufferView 和 DataView 类型:

if (Object.prototype.toString.call(yourObject.buffer) === "[object ArrayBuffer]") {
     // It's either an ArrayBufferView or a DataView
}
于 2014-07-09T06:02:22.427 回答
1

所有类型化的数组都继承自 ArrayBuffer。此类型包含一个 byteLength 属性,因此只需检查此属性是否可用。

function isTypedArray(obj)
{
    return !!obj && obj.byteLength !== undefined;
}
于 2017-10-29T11:25:46.437 回答
0

实际查找所有返回TypedArray 的构造函数的简单方法:

isTypedArray = _ => _?.prototype?.__proto__?.constructor?.name == "TypedArray";
for (const key of Object.getOwnPropertyNames(window)) {
  const obj = window[key];
  if (isTypedArray(obj)) {
    console.log(key, "is a TypedArray");
  }
}

当前 Chrome 中的输出:

Uint8Array is a TypedArray
Int8Array is a TypedArray
Uint16Array is a TypedArray
Int16Array is a TypedArray
Uint32Array is a TypedArray
Int32Array is a TypedArray
Float32Array is a TypedArray
Float64Array is a TypedArray
Uint8ClampedArray is a TypedArray
BigUint64Array is a TypedArray
BigInt64Array is a TypedArray
于 2022-02-12T11:12:48.933 回答