YUI.Lang is buggy?

Сижу я, значит, никого не трогаю, починяю примус пишу один модуль, и тут выясняется неприятное: оказывается, в YUI 3.0.0.pr2, модуле Lang методы isNumber и isBoolean того. Не этого. В смысле, бажные:

    alert(YUI.Lang.isNumber(new Number(1))); // false
    alert(YUI.Lang.isBoolean(new Boolean(true))) // false

Неприятно.

Лезу в код, и вижу:

// для простоты восприятия я выкинул все лишнее, относящееся только к YUI
isBoolean = function(o) {
    return typeof o === 'boolean';
};
 
isNumber = function(o) {
    return typeof o === 'number' && isFinite(o);
};

Придется править ручками.

Как известно, typeof объекта Boolean возвращает 'object'. Лезу в Boolean Reference, что на w3schools, и вижу, что у Boolean есть метод, который мне поможет – valueOf. Правлю isBoolean на что-то вроде:

isBoolean = function(o) {
    return (typeof o === 'boolean' || (o !== null && typeof o === 'object' && (typeof o.valueOf() === 'boolean')));
};

Тесты прогоняются на ура. Идем дальше. Смотрим в Number Reference, и по накатанной правлю и isNumber:

isNumber = function(o) {
    return ((typeof o === 'number') || (o !== null && typeof o === 'object' && (typeof o.valueOf() === 'number')) && isFinite(o);
};

Казалось бы, все круто? Не совсем.

alert(isNumber(new Date())); // return true;

Хм. Ну, давайте еще добавлю проверку на то, что это не Date.

isNumber = function(o) {
    return ((typeof o === 'number') || (o !== null && typeof o === 'object' && !(o instanceof Date))) && (typeof o.valueOf() === 'number')) && isFinite(o);
};

Теперь все работает нормально, но какой монстрик-то жуткий получается. Ладно, в идиота я наигрался, пора и голову включить:

isBoolean = function(o) {
    return typeof o === 'boolean' || o instanceof Boolean;
};
 
isNumber = function(o) {
    return (typeof o === NUMBER || o instanceof Number) && isFinite(o);
};

Вуаля. Пойду на форум YUI рапортовать о баге. Всем спасибо за внимание.

6 комментариев to “YUI.Lang is buggy?”

  1. >> Пойду на форум YUI рапортовать о баге.

    Какая же это бага? Это скорее вы чего-то странного хотите :) Boolean и Number это объекты-обертки над примитивными типами данных boolean и number. Методы YUI.Lang.isBoolean и YUI.Lang.isNumber как раз и проверяют примитивного ли типа переменная.

    Кстати, я вообще не понимаю зачем использовать эти объекты в явном виде и писать new Boolean, new Number и new String. Если нужны методы этих объектов, то примитивные типы boolean, number и string автоматически оборачиваются в эти объекты:

    var a = 123.45678;
    alert(a.toFixed(3));

    Если же очень хочется писать new Number, то у полученного объекта есть метод valueOf, который возвращает «обернутое примитивное значение». Результат вызова valueOf и передавайте в YUI.Lang.isNumber, а курочить YUI не надо :)

  2. <quote>Какая же это бага? Это скорее вы чего-то странного хотите :) Boolean
    и Number это объекты-обертки над примитивными типами данных boolean и
    number. </quote>
    Любопытно. Если мне не изменяет память, встроенные типы данных — это
    Undefined, Null, Boolean, Number, String, Object. А примитивы boolean и
    number – это что-то вроде «примитивных значений» соответствующих встроенных
    типов. Хотя за правильность формулировки не ручаюсь, лень лезть в спеку.

    <quote>Методы YUI.Lang.isBoolean и YUI.Lang.isNumber как раз и проверяют
    примитивного ли типа переменная.</quote>
    Я хочу не странного, а того, чтобы эти методы возвращали true, если в них
    передаешь примитив или встроенный тип.

    <quote>Кстати, я вообще не понимаю зачем использовать эти объекты в явном
    виде</quote>
    Не знаю :)

  3. http://www.ecma-international.org/publications/...

    Не поленился посмотреть спецификацию:

    4.3.2 Primitive Value
    A primitive value is a member of one of the types Undefined, Null, Boolean, Number, or String. A primitive value is a datum that is represented directly at the lowest level of the language implementation.

    4.3.3 Object
    An object is a member of the type Object. It is an unordered collection of properties each of which
    contains a primitive value, object, or function. A function stored in a property of an object is called a
    method.

    4.3.20 Number Type
    The type Number is a set of values representing numbers. In ECMAScript, the set of values represents the double-precision 64-bit format IEEE 754 values including the special “Not-a-Number” (NaN) values, positive infinity, and negative infinity.

    4.3.21 Number Object
    A Number object is a member of the type Object and is an instance of the built-in Number object. That is, a Number object is created by using the Number constructor in a new expression, supplying a number as an argument. The resulting object has an implicit (unnamed) property that is the number. A Number object can be coerced to a number value by calling the Number constructor as a function.

    ———————–

    new Number возвращает именно объект (Object).

    Кстати, немаловажно заметить, что примитивные типы передаются по значению, в то время как объекты передаются по ссылке.

  4. С одной стороны, вы правы:

    var a = new Number();

    alert(typeof a === 'object' && a instanceof Number && a instanceof Object);
    // true

    Получается, Number Object это подобъект (ну, или что-то в этом роде) типа
    Object.
    А объект Number экземпляр встроенного объекта Number.

    И ситуация с Boolean и String симметричная.

    А с другой стороны, типов (в значении «набор значений данных») все равно
    шесть – Undefined, Null, Boolean, Number, String и Object. Мы это знание
    получим, прочитав 8 (стр. 31)

  5. Да в общем-то и спорить не о чем :) Главное, что и я и вы понимаем, что new Number() возвращает Object.

    Просто я считаю, что YUI.Lang.isNumber проверяет именно тип переменной и должен возвращать true только если переменная типа Number.

  6. Я все же думаю, что правильнее будет такое поведение:

    var a = new Number(1);
    YUI.Lang.isObject(a); // true
    YUI.Lang.isNumber(a); // true
    

    Потому что a в данном случае – объект, но, одновременно, позволяет выполнять над собой операции, свойственные числам.

    var a = new Number(2), b = new Number(22);
     
    b/a; // 11
    b + a; // 24

Оставить комментарий

Последние твиты