В настоящее время я изучаю JavaScript promise.

Меня учили, что если объект / функция содержит в себе функцию-член с именем then(..), то объект / функция будет распознаваться как promise like object, независимо от того, является ли объект / функция истинным объектом обещания или не.

Итак, я придумал следующий код.

var aPromise = new Promise(function (resolve, reject){});
aPromise instanceof Promise; //prints true in chrome console


var a = {
    then: function(){}
};

a instanceof Promise;

Но после выполнения a instanceof Promise в консоли Chrome false был напечатан.

Почему это происходит? Я делаю что-то не так или мое понимание того, что такое объект, подобный обещанию, неверно?

2
Thor 29 Авг 2017 в 05:15

4 ответа

Лучший ответ

A. instanceof

Технически, выражение Javascript a instanceof b проверяет

  • a является объектом (который включает функции, потому что они являются объектами),
  • «b» - это функция конструктора, которая включает классы, потому что объявления и выражения, использующие ключевое слово class, создают функции конструктора,
  • значение b.prototype находится в цепочке наследования a. Это означает, что a был создан b, или где-то еще в цепочке наследования a существует объект, созданный b.

Если для цепочки наследования объектов задано свойство prototype его конструктора, aPromise в вашем коде является экземпляром Promise, поскольку Promise.prototype является первой записью в цепочке прототипов. , Вторая запись в цепочке прототипов - Object.prototype, поэтому aPromise также является экземпляром Object.

a создается и инициализируется Object в ответ на синтаксис инициализатора объекта {..}. Object.prototype является первым объектом в его наследовании, поэтому он является "экземпляром" Object и ничем иным.

B. тоглы

Объекты с возможностью "отображения" с помощью метода .then описаны в спецификации + обещания, в которой обещания ES6 основаны.

Распознавание и обработка объектов позволяют различным программным библиотекам, каждая из которых использует свой собственный код конструктора Promise, иметь дело с обещаниями, созданными другой библиотекой, созданной с использованием другого конструктора. Простая проверка, является ли объект обещания экземпляром собственного конструктора библиотеки Promise, предотвращает использование объектов обещаний между библиотеками.

Единственный случай, когда реализация обещания должна иметь дело с «тогдашним» объектом, - это когда обещание сторонней библиотеки используется для разрешения обещания, созданного реализацией. Стандартный метод решения этой проблемы заключается в реализации для создания новой пары функций разрешения / отклонения, скажем, resolve2 и reject2 для решаемого обещания, и вызова метода then затем. передать установленное значение. В псевдокоде:

if promiseA, instance of PromiseA, is resolved with promiseB, instance of PromiseB {

    PromiseA code creates new resolve2/reject2 functions for promiseA
    and calls the thenable's then method as:

         promiseB.then( resolve2, reject2);
}
// ....
If promiseB remains pending, promiseA remains pending;
If promiseB is settled, promiseA becomes fulfilled or rejected with the same value.
1
traktor53 29 Авг 2017 в 05:14

Используйте метод Promise.resolve , чтобы преобразовать ваш объект ('a') в Promise:

var a = Promise.resolve({
    then: function(){}
});
1
leandro martinez 17 Мар 2019 в 21:40

Оператор instanceof проверяет, имеет ли объект в своей цепочке прототипов свойство prototype конструктора.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof

Это не имеет отношения к (возможно, даже противоположно?) Типизированию утки, где методы и свойства объекта определяют симантику объекта, что позволяет вам рассматривать его как вас может обрабатывать Promise, но это никоим образом не делает его экземпляром или потомком Promise.

( акцент добавлен мной )

В компьютерном программировании с объектно-ориентированными языками программирования, типирование утки - это стиль набора текста, при котором методы объекта и свойства определяют действительную семантику, , а не ее наследование от определенного класса или реализации конкретного интерфейс .

https://en.wikipedia.org/wiki/Duck_typing через https://ericlippert.com/2014/01/02/what-is-duck-typing /

Конкретный пример в javascript - это nodeList; это похоже на массив, потому что вы можете получить доступ к членам списка узлов по целочисленному индексу, но это не массив или instanceof массив.

1
chiliNUT 29 Авг 2017 в 02:35

Если вы хотите проверить доступный объект (как Promise like)

if ((typeof a === 'function' || typeof a === 'object') && typeof a.then === 'function') {
    // a is "Promise like" (or a Promise)
}
1
Jaromanda X 29 Авг 2017 в 02:30