Написание библиотеки и в конечном итоге конечная цель - определить, является ли объект наблюдаемым. Однако я точно не знаю, передаст ли пользователь ненаблюдаемое значение.

Я удивлен, что даже примитивы в JS имеют свойство конструктора, например:

const bool = true;
console.log(bool.constructor.name);

const string = 'foo';
console.log(string.constructor.name);

const num = 5;
console.log(num.constructor.name);

Все определенные, что меня удивляет, я бы предположил, примитивные значения в JS не будет иметь конструктора (по соображениям производительности, например, в Java).

, поэтому мой вопрос: есть ли какое-либо значение в JS, для которого конструктор был бы неопределенным?

В конечном счете, я хочу создать достойный тест, что значение является наблюдаемым, вот мой предварительный тест:

module.exports = function isObservable(val) {

    return (val && typeof val.subscribe === 'function'
    && val.constructor && /Observable/.test(val.constructor.name));

};
1
Alexander Mills 9 Янв 2017 в 02:51

4 ответа

Лучший ответ

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

Теперь, когда вы изменили вопрос, чтобы показать, что вы действительно пытаетесь сделать (определить, передали ли вы наблюдаемый объект), у вас есть пара вариантов:

  1. Протестируйте instanceof, чтобы узнать, происходит ли оно от известного базового объекта.
  2. Протестируйте объект, чтобы увидеть, имеет ли он известные и ожидаемые свойства объекта, который ведет себя так, как вы хотите. Это называется типизацией "утка". Если он крякает как утка, значит, это утка, и этого достаточно для того, что вы пытаетесь сделать, даже если вы не проверили его ДНК.

Я бы посоветовал вам расширить то, что вы имели с этим:

return (val && 
        typeof val.subscribe === 'function' && 
        typeof val.unsubscribe === 'function')

Добавить еще пару свойств / методов, которые, как вы ожидаете, будут на допустимом наблюдаемом объекте. Вы можете сделать тест настолько строгим, насколько вам нужно (проверить на 10 отдельных методов, если хотите, или даже вызвать пару методов без побочных эффектов, чтобы увидеть, возвращают ли они желаемое значение), но в действительности вы, вероятно, просто хотите убедиться, что что это несколько пахнет, как будто это наблюдаемое, а затем, если вызывающий абонент дает вам полуобработанное наблюдаемое, это своего рода проблема. Скорее всего, ваша настоящая цель здесь - просто сообщить разработчику, когда он допустил ошибку в программировании, чтобы вы могли «на раннем этапе» выдать исключение во время их разработки, которое показывает, что он передал неправильный тип объекта. Для этого достаточно простейшего теста на запах. Как правило, вы не заинтересованы в тестировании на субаренду.

Нет никаких причин проверять наличие большего количества свойств, чем вы собираетесь использовать. Если кто-то хочет создать свою собственную версию наблюдаемой, которая поддерживает свойства, которые вы используете, то ему следует разрешить сделать это, так что вам не нужно беспокоиться об этом. Если они пытаются использовать что-то, что выглядит как наблюдаемое, но не совсем реализует правильные интерфейсы на объекте, то это как бы то, что они не дают вам легитимное наблюдаемое, не совсем на вашем API.

1
jfriend00 9 Янв 2017 в 01:13

У каждого значения / объекта в JS есть конструктор?

Простой ответ - «НЕТ», потому что мы знаем, что null и undefined не «имеют» конструктор. Таким образом, есть значения, которые "не имеют конструктора"

Более точный ответ: «Мы НЕ ЗНАЕМ, имеет ли null конструктор, потому что если вы попытаетесь выполнить:« let a = null.constructor », ваша программа аварийно завершает работу .

Но затем в своем комментарии вы говорите: «Мне особенно интересно, есть ли обстоятельства, для которых конструктор может быть неопределенным». Это тоже был мой вопрос.

Другими словами, есть ли случай, в котором мы можем выполнить a.constructor === undefined и получить истину в результате?

Ответ на этот вопрос «ДА», как показано в следующем фрагменте кода:

let a = {};    
a.constructor = undefined;
console.log (a.constructor); 
// -> console shows: undefined
1
Panu Logic 11 Дек 2017 в 16:40

undefined и null не имеют свойства constructor.

Значения, такие как числа, по-видимому, имеют constructor, но на самом деле являются «особыми», потому что

x = 3
x.y = "z"         // no problem
console.log(x.y)  // undefined!

«обернутые» числа (x = new Number(42)) вместо этого являются обычными объектами, и вы можете хранить в них дополнительные свойства. Поэтому, хотя 3 объявляет Number в качестве конструктора, его вызов не генерирует значение того же типа, что и число 3.

3
6502 8 Янв 2017 в 23:57

За исключением примитивов 'null' и 'undefined', все остальные примитивы имеют свойство конструктора.

1
Sri 9 Янв 2017 в 00:10