2011-12-20 2 views
15

Может ли кто-нибудь объяснить следующее?Ошибка несоответствия

[] instanceof Array; // true 
'' instanceof String; // false 
+1

Также 'typeof" "' '' '' string ''и' typeof [] 'is' "object" '(вы ожидали бы' 'array'', но в порядке я могу жить с этим) – Halcyon

+0

Угадай, «быть примитивным, но [] объектом? –

+2

+1 Интересно, потому что '" ".constructor === String'. – pimvdb

ответ

14

Обратите внимание на следующее:

"" instanceof String;    // => false 
new String("") instanceof String; // => true 

instanceof требует объект, но "" является строковым, а не объект типа String. Обратите внимание на следующие типы с помощью функции typeof:

typeof ""    // => "string" 
typeof new String("") // => "object" 
typeof []    // => "object" 
typeof new Array() // => "object" 
+0

В чем же разница между строкой 'literal' и' String' и почему она (по-видимому) важна? Насколько я знаю, их можно использовать взаимозаменяемо, но в результате вы не можете использовать 'instanceof' для проверки того, что-то является« строкой » – Halcyon

+1

. Но это не' [] 'литерал массива так же, как' '' 'является строковым литералом? – FishBasketGordo

+0

@FishBasketGordo массив может содержать все виды примитивов и объектов. –

11

Это потому, что '' примитивно, не является объектом.

Некоторые примитивы в JavaScript могут иметь обертку объекта. Они создаются при создании экземпляра обертки с использованием встроенного конструктора с new.

new обычно необходим, потому что часто функция будет принудительно применяться к примитиву, если вы исключаете new.

typeof new String(''); // "object" 
typeof String('');  // "string" 
typeof '';    // "string" 

Примитивы, которые имеют обертки объекта являются string, number и boolean.

Примитивы, которые не являются null и undefined.

+0

Итак, что такое примитив (т. Е. Объект без оболочки) '[]'? – Randomblue

+2

Randomblue: Нет. Массив всегда является объектом. –

+0

@ Randomblue не существует. Почему был примитив? – Raynos

3

'' не является примером чего-либо; это примитивный тип, и он работает почти так же, как 5.5 или true. Существует разница между примитивом строки и объектом String. См:

new String('') instanceof String; // true 

Все создано с new String(), new Number() или new Boolean() является объектом обертка вокруг примитивного типа, и они не то же самое.

Для проверки строк и т.д., используйте typeof вместо:

typeof '' === 'string'; // true 

Для проверки как, используйте:

Object.prototype.toString.call('') === '[object String]'; // true 
Object.prototype.toString.call(new String('')) === '[object String]'; // true 

Есть несколько причин, чтобы использовать Object.prototype.toString.call для общий код, для массивов, строк, номеров и booleans. Они:

  1. Для строк, чисел и булевых объектов люди могут передавать экземпляры объектов-оболочек вместо примитивных типов. Они обычно функционируют одинаково (с неявным valueOf()), и поэтому вы должны принимать их, если записываете библиотечный код.
  2. Для массивов, если вы получаете массив из другого окна (скажем, из <iframe>), то с помощью instanceof Array вернется false. Метод Object.prototype.toString.call работает для всех целей.

Это то, что делают jQuery и другие крупные, популярные библиотеки.

1

Я сделал некоторое копание, и я полагаю, что это связано с string interning, который является оптимизацией компилятора.

Хорошо, готов к некоторым ошибкам? : D

"abc" == "abc"; // true 
"abc" === "abc"; // true 

Я полагаю, что это действительно так, «строка интернирование», который по совпадению также делает много смысла, концептуально (яй для получения «строки» вправо).

new String("abc") == new String("abc"); // false 
new String("abc") === new String("abc"); // false 

Это имеет смысл, если предположить String является объектом и объект равен только самому себе и не равен объекта с подобным внутренним состоянием. Как в Java (или как это было в любом случае).

И теперь для кикера:

(new String("abc")).substr(0,3) === (new String("abc")).substr(0,3); // true! 

Так, видимо, интерпретатор JavaScript будет всегда предпочитают строку интернирование над использованием String объекта.

Затем я должен спросить, что такое использование объекта String? По-видимому, он не играет с друзьями.

+0

Первый, '' abc "===" abc "', не из-за интернирования строк. Строгое равенство работает так же, как и для примитивных типов. '===' - это только «reference-equals» для объектов. – Ryan

+0

Строка 'type' существует только там, где вы можете расширить свой прототип, а также позволить вам создавать строки типа« Objects ». То есть объекты (похожие на указатели на C) будут только '===', если они являются «одинаковыми указателями» – Adaptabi

Смежные вопросы