Почему есть два вида строк JavaScript? - PullRequest
37 голосов
/ 01 апреля 2011

Этот только что нанес мне сильный удар. Я не знаю, так ли это со всеми браузерами (у меня нет другого компетентного браузера для тестирования), но по крайней мере Firefox имеет два типа строковых объектов.

Откройте консоль Firebugs и попробуйте следующее:

>>> "a"
"a"
>>> new String("a")
String { 0="a"}

Как вы можете видеть визуально, Firefox по-разному относится к new String("a") и "a". В противном случае, однако, оба вида строк ведут себя одинаково. Например, есть доказательства того, что оба используют один и тот же объект-прототип:

>>> String.prototype.log = function() { console.log("Logged string: " + this); }
function()
>>> "hello world".log()
Logged string: hello world
>>> new String("hello world").log()
Logged string: hello world

Так что, очевидно, оба одинаковы. То есть, пока вы не спросите тип.

>>> typeof("a")
"string"
>>> typeof(new String("a"))
"object"

Мы также можем заметить, что когда this является строкой, это всегда форма объекта:

>>> var identity = function() { return this }
>>> identity.call("a")
String { 0="a"}
>>> identity.call(new String("a"))
String { 0="a"}

Продвинувшись немного дальше, мы видим, что не-строковое представление не поддерживает никаких дополнительных свойств, но строка объекта поддерживает:

>>> var a = "a"
>>> var b = new String("b")
>>> a.bar = 4
4
>>> b.bar = 4
4
>>> a.bar
undefined
>>> b.bar
4

Кроме того, забавный факт! Вы можете превратить строковый объект в необъектную строку, используя функцию toString():

>>> new String("foo").toString()
"foo"

Никогда не думал, что будет полезно позвонить String.toString()! В любом случае.

Итак, во всех этих экспериментах возникает вопрос: почему в JavaScript есть два типа строк?


Комментарии показывают, что это также относится к каждому примитивному типу JavaScript (включая числа и bool).

Ответы [ 3 ]

14 голосов
/ 01 апреля 2011

В Javascript есть два типа строк - литеральные строки и объекты String. Они ведут себя немного по-другому. Основное различие между ними заключается в том, что вы можете добавлять дополнительные методы и свойства к объекту String. Например:

var strObj = new String("object mode");
strObj.string_mode = "object"
strObj.get_string_mode = function() { return this.string_mode; }

// this converts it from an Object to a primitive string:
str = strObj.toString();

Строковый литерал просто временно приводится к объекту String для выполнения любого из основных методов.

Те же виды концепций применимы и к другим типам данных. Подробнее о примитивных типах данных и объектах .

EDIT

Как отмечается в комментариях, строковые литералы не являются примитивными строками, а являются "константой литерала, тип которой является встроенным примитивным [string] значением", цитируя этот источник .

2 голосов
/ 01 апреля 2011

Сравнение строковых значений с строковыми объектами.

"a" - строковое значение.

"a" === "a"; // true

new String("a") - строковый объект.

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

Там обе строки."a" просто получает строковое значение "a", где new String("a") создает новый строковый объект, который внутренне имеет строковое значение "a"

0 голосов
/ 12 августа 2011

Еще одна важная вещь, которую следует запомнить:

typeof "my-string" // "string"
typeof String('my-string') // 'string'
typeof new String("my-string") // "object". 

Следовательно, при проверке того, является ли аргумент или переменная строкой, необходимо выполнить как минимум следующее.

function isString(arg) {
  if (!arg) {
    return false;
  }
  return typeof arg == "string" || arg.constructor == String;
}

Вышеприведенная функция все равно не будет работать, если вы передадите объект String из другого фрейма / фрейма.То есть:

frames[0].myStringVar.constructor != frames[1].myStringVar.constructor

Это потому, что конструктор String отличается для каждого контекста окна.Следовательно, надежный метод isString будет

function isString(obj) {
   return Object.prototype.toString.call(obj) == "[object String]";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...