Строковый объект по сравнению с литералом - изменение прототипа? - PullRequest
5 голосов
/ 21 сентября 2010

Мне интересно, почему кажется, что добавление метода к прототипу строкового литерала работает, а добавление свойства - нет?Я играл с идеями, связанными с этим вопросом , и получил следующий код:

String.prototype._str_index1 = 0;
String.prototype._str_reset = function() {
    this._str_index1 = 0;
};
String.prototype._str_substr = function(len) {
  var ret = this.substr(this._str_index1, len);
  this._str_index1 = this._str_index1 + len;
  return ret;
};

var testString = new String('Loremipsumdolorsitamet,consectetur');
log(testString._str_substr(5));
log(testString._str_substr(4));
​

Это прекрасно работает.Однако если я изменю третью последнюю строку на:

var testString = 'Loremipsumdolorsitamet,consectetur';

... кажется, что хотя метод _str_substr существует и может вызываться в строковом литерале, значение свойства _str_index1всегда 0.

Что случилось?

Ответы [ 2 ]

8 голосов
/ 21 сентября 2010

Строковый примитив преобразуется в временный объект String каждый раз, когда вы пытаетесь вызвать метод объекта String (механизм JavaScript внутренне преобразует строковый примитив в объект String при необходимости). После возврата этой функции объект String (ненавязчиво) преобразуется обратно в строковый примитив (под капотом), и этот новый примитив возвращается (и большую часть времени назначается переменной); каждый раз, когда вызывается метод объекта String .

Таким образом, после каждого вызова testString._str_substr, _str_index1 выбрасывается вместе с объектом, и при повторном вызове _str_substr создается новый объект (со сбросом _str_index1).

См. Также MDC :

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

2 голосов
/ 21 сентября 2010

Это происходит потому, что объект создается и сразу выбрасывается при назначении, потому что это строковый литерал.

Итак, в первой версии объект создается и сохраняется, поэтому testString - это объект, а не строковый литерал. Во втором случае объект создается и выбрасывается, поэтому все свойства теряются ...

Теперь попробуйте заменить эту строку на:

var testString = 'Loremipsumdolorsitamet,consectetur'._str_substr();

Интересно, правда? Он по-прежнему возвращает строковый примитив, но это можно исправить ...

String.prototype._str_substr = function(len) {
  var ret = this.substr(this._str_index1, len);
  this._str_index1 = this._str_index1 + len;
  return new String(ret);
};

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

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