2013-12-19 3 views
5

Это стало больше размышлять о том, как работает javascript, чем о реальной проблеме для исправления. В случае заявления типаАвтоматическое принуждение типа javascript

var str = 9 + " some words here"; 

Результат str var будет содержать значение «9 слов здесь». Мой вопрос заключается в том, какую функцию использует javascript для автоматического принуждения объекта Number '9' к строке, которая будет конкатенирована с объектом String «некоторые слова здесь», и эта функция изменена/переопределена.

Это началось с того, что мне нужно было выводить одиночные цифры с предшествующим 0 на странице. Этого было достаточно легко выполнить с функцией быстрого прототипа на номер объекта

Number.prototype.SpecialFormat = function() { 
    if(this < 10) { 
    return "0" + this; 
    } 
    else { 
    return this.toString(); 
    } 
}; 

И называют это с помощью простого (9).SpecialFormat() + " words here";

Но у меня интересно, если я мог бы переписать функцию ToString на абонентский номер

Number.prototype.toString = function() { 
    if(this < 10) { 
    return "0" + this; 
    } 
    else { 
    return this; 
    } 
}; 

, и пусть JavaScripts автоматическое преобразование обрабатывать его для меня, так что я мог бы использовать стандартный 9 + " words here";, чтобы получить тот же результат «09 слова здесь». Это не просто неявно работало, я должен был добавить добавление .toString к 9 (9).toString() + " words here" (что, если посмотреть дальше, привело бы к бесконечным циклам).

Так есть способ переопределить встроенные функции родного типа javascript?

* Примечание: Я понимаю, что это, скорее всего, «худшая идея когда-либо»

+3

См [добавление оператора] (http://www.ecma-international.org/ecma-262/5.1/#sec-11.6 .1) (шаг 7), а также [ToString] (http://www.ecma-international.org/ecma-262/5.1/#sec-9.8) и «[ToString Applied to the Number Type] (http : //www.ecma-international.org/ecma-262/5.1/#sec-9.8.1)». Похоже, что абстрактная операция 'ToString (number)' никогда не использует 'Number.prototype.toString' (на самом деле это наоборот). – apsillers

+0

Я думаю, именно поэтому я получаю ошибку «Максимальный размер стека вызовов», когда я использую String (this) в прототипе toString. –

+0

Я предполагаю, что в этом случае JavaScript построен иначе, чем другие объектно-ориентированные языки, где вы можете переопределить операторы, применяемые к объектам. Мне кажется, что конкатенация строк выполняется внутренне интерпретатором, игнорируя все переопределенные методы. – VisioN

ответ

3

addition operator принуждают свои аргументы строки в шаге 7:

  • Если Тип (lprim) является строка или Type (rprim) является String, затем
    • Возвращает строку, которая является результатом объединения ToString (lprim), а затем ToString (rprim)

ToString operation имеет специальные правила для чисел, подробно в разделе "ToString Applied to the Number Type".

Похоже, что абстрактная операция ToString(number) никогда не использует Number.prototype.toString. На самом деле, ti наоборот: default Number.prototype.toString function использует абстрактный числовой алгоритм ToString. Таким образом, невозможно переопределить поведение по умолчанию для стробирования чисел во время принуждения типа в ECMAScript 5, потому что нет возможности изменить определяемую языком работу ToString.

ToString делает использовать toString метод цели при принуждении объектов к строкам, но не нумеровать примитивные значения.

3

(строго говоря, не ответ, но мне нужно некоторое пространство)

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

var n = 9; 
typeof n; // "number" 
n instanceof Number; // false!! 

n = new Number(9); 
n instanceof Number; // true, oh thank God 
typeof n; // "object" what!! 

Кроме того, toString на Number на самом деле не работает:

Number.prototype.toString = function() { return "foo" + this; }; 
var n = new Number(9); 
"" + n; // "9", not "foo9" 

Путь, чтобы избежать путаницы этого является наличие:

var ns = { 
    number: { 
     specialFormat: function() /* .. */ } 
    } 
} 

ns.number.specialFormat(9); // "09" 
+0

'n = Number (9);' в первом блоке кода должно быть «n = новое число (9);». В противном случае вы просто вызываете функцию Number, чтобы преобразовать параметр в числовой примитив, который он уже есть. Поэтому следующие две строки будут такими же, как две строки перед ним. – Sam

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