在 JavaScript 中,可以使用多种方式判断一个对象是否是 Promise。以下是几种常见的方法:
一、使用 typeof 和 then 方法
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` 对象)
🔹 优点:更精准,能区分真正的 Promise 和 thenable 对象
🔹 缺点:无法判断跨 iframe 的 Promise(不同 window 的 Promise 可能有不同的 prototype)
三、结合 then 和 catch(最严谨)
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 兼容性不好
五、推荐的最佳实践
如果需要严格区分 Promise 和 thenable,使用:
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 | 仅判断原生 Promise | ❌ | iframe 跨域问题 |
typeof obj.then === 'function' && typeof obj.catch === 'function' | 兼容 Promise A+ 规范 | ✅ | 伪造对象 |
Object.prototype.toString.call(obj) === "[object Promise]" | 精确匹配 Promise | ❌ | 不能识别 thenable |
最稳妥的方式是 instanceof Promise 或 then + catch 组合方式,具体选择哪种,取决于你的实际需求。