使用 Object.prototype.toString 时的边缘情况是什么?

What are the edge cases when using Object.prototype.toString?

到目前为止,我一直依靠 Object.prototype.toString.call(x) 来区分 Javascript 中的不同本机对象类型,尤其是数组。

如果你对数组进行子类化,你会得到一些奇怪的行为:

function Ctor() {}
Ctor.prototype = Object.create(Array.prototype);
var x = new Ctor();
x.push(1);

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

可能这已记录在 ES5 规范中(并且不再是 ES6 中的问题),但我认为这是该语言当前版本的一个怪癖。我对相应的功能进行了如下调整:

function objTypeOf(deep, type) {
  return function _objTypeOf(x) {
    do {
      if (Object.prototype.toString.call(x).slice(8, -1).toLowerCase() === type) return true;
      x = Object.getPrototypeOf(x);
    } while(deep && x !== null);

    return false;
  };
}

var arr = objTypeOf(false, "array"),
 arrP = objTypeOf(true, "array"); // array prototype

console.log(arr(x)); // false
console.log(arrP(x)); // true

objTypeOf 检查当前对象和整个原型链,直到类型匹配。它接受一个对象,即使只有一个原型匹配预期的类型。 objTypeOf 不是基于原型标识,而是基于字符串(缺少标识)。

我现在想知道在使用 Object.prototype.toString 时是否还有其他需要特殊处理的边缘情况?

好吧,你的问题不在于 Object.prototype.toString,而是你试图 subclass arrays。它只是行不通,toString 正确地告诉您创建数组失败。它只是一个 object 在它的原型链中有 Array.prototype (如果那是你关心的,使用 instanceof Array)。

无论如何,回答你的标题问题:

What are the edge cases when using Object.prototype.toString?

主持objects。任何不是原生 JS object 的东西,尽管看起来像一个,但可能 return 任何你没有想到的 [[Class]] 值。甚至在已知情况下,可调用 objects 不报告 Function.