Почему 4 не является экземпляром Number? - PullRequest
63 голосов
/ 23 января 2009

Просто любопытно:

  • 4 instanceof Number => false
  • новый номер (4) instanceof Number => true?

Почему это? То же самое со строками:

  • 'some string' instanceof String возвращает ложь
  • new String('some string') instanceof String => верно
  • String('some string') instanceof String также возвращает false
  • ('some string').toString instanceof String также возвращает false

Для объектов, массивов или функций оператор instanceof работает как положено. Я просто не знаю, как это понять.

[ новые идеи ]

Object.prototype.is = function() {
        var test = arguments.length ? [].slice.call(arguments) : null
           ,self = this.constructor;
        return test ? !!(test.filter(function(a){return a === self}).length)
               : (this.constructor.name ||
                  (String(self).match ( /^function\s*([^\s(]+)/im )
                    || [0,'ANONYMOUS_CONSTRUCTOR']) [1] );
}
// usage
var Newclass = function(){};  // anonymous Constructor function
var Some = function Some(){}; // named Constructor function
(5).is();                     //=> Number
'hello world'.is();           //=> String
(new Newclass()).is();        //=> ANONYMOUS_CONSTRUCTOR
(new Some()).is();            //=> Some
/[a-z]/.is();                 //=> RegExp
'5'.is(Number);               //=> false
'5'.is(String);               //=> true

Ответы [ 5 ]

62 голосов
/ 23 января 2009

value instanceof Constructor совпадает с Constructor.prototype.isPrototypeOf(value), и оба проверяют [[Prototype]] - цепочку value на наличие вхождения конкретного объекта.

Строки и числа являются примитивными значениями , а не объектами и, следовательно, не имеют [[Prototype]], поэтому он будет работать, только если вы оберните их в обычные объекты (называемые «боксом» в Java).

Также, как вы заметили, String(value) и new String(value) делают разные вещи: если вы вызываете функции конструктора встроенных типов без использования оператора new, они пытаются преобразовать ('cast') аргумент для конкретного типа. Если вы используете оператор new, они создают объект-оболочку.

new String(value) примерно эквивалентен Object(String(value)), который ведет себя так же, как new Object(String(value)).


Еще немного о типах в JavaScript: ECMA-262 определяет следующие типы примитивов: Undefined , Null , Boolean , Number и Строка . Кроме того, есть тип Объект для вещей, которые имеют свойства.

Например, функции имеют тип Object (они просто имеют специальное свойство, называемое [[Call]]), а null является примитивным значением типа Null . Это означает, что результат оператора typeof на самом деле не возвращает тип значения ...

Кроме того, объекты JavaScript имеют другое свойство, называемое [[Class]]. Вы можете получить его через Object.prototype.toString.call(value) (это вернет '[objectClassname]'). Массивы и функции имеют тип Object , но их классы: Array и Function .

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


Также вы можете попробовать эту улучшенную версию typeof:

function typeOf(value) {
    var type = typeof value;

    switch(type) {
        case 'object':
        return value === null ? 'null' : Object.prototype.toString.call(value).
            match(/^\[object (.*)\]$/)[1]

        case 'function':
        return 'Function';

        default:
        return type;
    }
}

Для примитивов он вернет их тип в нижнем регистре , для объектов он вернет их class в title case .

Примеры:

  • Для примитивов типа Число (например, 5), он вернет 'number', для объектов-оболочек класса Число (например, new Number(5)), будет возвращено 'Number';

  • Для функций возвращается 'Function'.

Если вы не хотите различать примитивные значения и объекты-обертки (по какой-либо, возможно, неправильной причине), используйте typeOf(...).toLowerCase().

Известными ошибками являются некоторые встроенные функции в IE, которые рассматриваются как 'Object' и возвращаемое значение 'unknown' при использовании с некоторыми объектами COM +.

13 голосов
/ 23 января 2009

Вы можете попробовать оценить:

>>> typeof("a")
"string"
>>> typeof(new String("a"))
"object"
>>> typeof(4)
"number"
>>> typeof(new Number(4))
"object"
2 голосов
/ 23 января 2009

Как указано в ответе Кристофа, строковые и числовые литералы не совпадают с объектами String и Number. Если вы используете какой-либо из методов String или Number для литерала, скажите

'a string literal'.length

Литерал временно преобразуется в объект, метод вызывается и объект отбрасывается.
Литералы имеют некоторые явные преимущества перед объектами.

//false, two different objects with the same value
alert( new String('string') == new String('string') ); 

//true, identical literals
alert( 'string' == 'string' );

Всегда используйте литералы, чтобы избежать неожиданного поведения!
Вы можете использовать Number () и String () для ввода типа, если вам нужно:

//true
alert( Number('5') === 5 )

//false
alert( '5' === 5 )
1 голос
/ 28 ноября 2015

В случае простых чисел, метод isNaN также может помочь вам.

1 голос
/ 23 января 2009

Это нюанс Javascript, который, как я обнаружил, улавливает некоторые. Оператор instanceof всегда приводит к значению false, если LHS не относится к типу object.

Обратите внимание, что new String('Hello World') не приводит к типу string, но является object. Оператор new всегда приводит к объекту. Я вижу такие вещи:

function fnX(value)
{
     if (typeof value == 'string')
     {
          //Do stuff
     }
}
fnX(new String('Hello World'));

Ожидается, что произойдет "Do Stuff", но этого не произойдет, потому что тип значения - это объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...