我正在开发一款游戏,我们会为数学类型广泛使用类型数组(Float32Arrays)。我们从JSON保存并加载游戏状态。 JSON stringify输出的一个示例是针对这样的数组(在Chrome中):
"{"0":0,"1":0,"2":0,"length":3,"byteLength":12,"byteOffset":0,"buffer":{"byteLength":12}}"
这会浪费空间并导致它们作为不方便的对象加载。理想情况下,我们可以使用stringify'replacer'函数来测试变量是否是类型化数组,然后在这种情况下将其转换为bog标准数组。不幸的是,我不确定如何可靠地测试变量是否是类型化数组。
任何帮助?
答案 0 :(得分:19)
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
答案 1 :(得分:13)
如果您对Float32Array
或 Float32Array
的子类感到满意,他们将来自同一个 realm < / em>(松散地,窗口)作为您正在检查的代码see Anton's answer using instanceof
。
如果你需要知道它是具体一个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]
等)返回一个有用的字符串。Per specification,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));
答案 2 :(得分:12)
您也可以使用yourObject instanceof Float32Array
构造。
如果您的对象是true
和Float32Array
的实例,则会返回false
。
if (yourObject instanceof Float32Array) {
// your code here
}
答案 3 :(得分: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
或类似的是确定特定类型的最佳方式。
答案 4 :(得分:2)
如果您想要一个更通用的测试来捕获任何可以使用的ArrayBufferView和DataView类型:
if (Object.prototype.toString.call(yourObject.buffer) === "[object ArrayBuffer]") {
// It's either an ArrayBufferView or a DataView
}
答案 5 :(得分:2)
我找到了一个更好的方法,如果你想测试每一个可能的 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;
})();
答案 6 :(得分:1)
所有类型化数组都继承自ArrayBuffer。此类型包含byteLength属性,因此请检查此属性是否可用。
function isTypedArray(obj)
{
return !!obj && obj.byteLength !== undefined;
}