从入门到精通:JavaScript中判断Promise的完整方案

171 阅读2分钟

在 JavaScript 中,可以使用多种方式判断一个对象是否是 Promise。以下是几种常见的方法:


一、使用 typeofthen 方法

Promise 对象有 then 方法,我们可以通过 typeof obj.then === 'function' 来判断:

js
复制编辑
function isPromise(obj) {
  return !!obj && typeof obj.then === 'function';
}

// 测试
console.log(isPromise(new Promise(() => {}))); // true
console.log(isPromise({ then: function() {} })); // true(但可能是类 Promise)
console.log(isPromise(null)); // false
console.log(isPromise(123)); // false
console.log(isPromise({})); // false

🔹 优点:简单可靠
🔹 缺点:可能会误判类似 Promise 的对象(例如手写的 thenable 对象)


二、使用 instanceof Promise

js
复制编辑
function isPromise(obj) {
  return obj instanceof Promise;
}

// 测试
console.log(isPromise(new Promise(() => {}))); // true
console.log(isPromise(Promise.resolve(123))); // true
console.log(isPromise({ then: function() {} })); // false(不会误判 `thenable` 对象)

🔹 优点:更精准,能区分真正的 Promisethenable 对象
🔹 缺点:无法判断跨 iframePromise(不同 windowPromise 可能有不同的 prototype


三、结合 thencatch(最严谨)

js
复制编辑
function isPromise(obj) {
  return !!obj && typeof obj.then === 'function' && typeof obj.catch === 'function';
}

// 测试
console.log(isPromise(new Promise(() => {}))); // true
console.log(isPromise(Promise.resolve())); // true
console.log(isPromise({ then: function() {} })); // false(过滤掉 `thenable`)
console.log(isPromise({ then: () => {}, catch: () => {} })); // true(仍然能识别 `thenable`)

🔹 优点:既能识别 Promise,也能识别符合 Promise 规范thenable 对象
🔹 缺点:仍可能被手写 then/catch 对象欺骗


四、使用 Object.prototype.toString

js
复制编辑
function isPromise(obj) {
  return Object.prototype.toString.call(obj) === "[object Promise]";
}

// 测试
console.log(isPromise(new Promise(() => {}))); // true
console.log(isPromise(Promise.resolve())); // true
console.log(isPromise({ then: function() {} })); // false
console.log(isPromise({})); // false

🔹 优点:精准匹配 Promise 类型
🔹 缺点:对手写 thenable 兼容性不好


五、推荐的最佳实践

如果需要严格区分 Promisethenable,使用:

js
复制编辑
function isPromise(obj) {
  return !!obj && (obj instanceof Promise || (typeof obj.then === "function" && typeof obj.catch === "function"));
}

这样既能识别 Promise,又能兼容符合 Promise A+ 规范的 thenable 对象。


六、总结

方法适用场景是否能识别 thenable可能误判
typeof obj.then === 'function'快速判断thenable
obj instanceof Promise仅判断原生 Promiseiframe 跨域问题
typeof obj.then === 'function' && typeof obj.catch === 'function'兼容 Promise A+ 规范伪造对象
Object.prototype.toString.call(obj) === "[object Promise]"精确匹配 Promise不能识别 thenable

最稳妥的方式是 instanceof Promisethen + catch 组合方式,具体选择哪种,取决于你的实际需求。