Случай несогласованности

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

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

Ответы

Ответ 1

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

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

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

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

Ответ 2

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

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

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

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

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

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

Ответ 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 для общего кода для массивов, строк, чисел и логических элементов. Это:

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

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

Ответ 4

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

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

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

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

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? По-видимому, он не играет со своими друзьями.