[javascript] создать прототип-наследник Number

kill-still

Стандартный подход не работает:

function BigNumber(a) {
Number.constructor.call(this, a);
}

BigNumber.prototype = new Number;
BigNumber.prototype.myMethod = function {
return 'bla-bla';
}

Немного уличной магии тоже не помогает:

function BigNumber(a) {
var n = Object.create(Number.prototype);
Number.constructor.call(n, a);
return n;
}

Работает как надо только такой говнокод:

function BigNumber(a) {
var n = new Number(a);
n.myMethod = function {
return 'bla-bla';
}
return n;
}

Кто-нибудь знает, что с этим прототипом (Number) не так, и как от него отнаследоваться?

istran

Стандартный подход не работает:
Потому что Number.constructor это не то, что ты хочешь. Number.constructor это функция которая конструировала функцию Number. Тебе же нужен нужен (new Number.constructor, который есть Number.
Кажется, правильно будет так:

function BigNumber(a) {
Number.call(this, a);
}

BigNumber.prototype = Object.create(Number.prototype);
BigNumber.prototype.myMethod = function {
return 'bla-bla';
}

PS: В JS я не очень силен и код не проверял.

kill-still

спасибо.

istran

А зачем собственно это тебе надо? Я попробовал сложить два объекта BigNumber, получил "Number.prototype.valueOf is not generic". Ты конечно можешь перегрузить valueOf, но сделать, чтобы результатом арифметических действий были объекты BigNumber невозможно.

kill-still

В MongoDB данные хранятся в long:
9223372036854775807 = Long.MAX_VALUE = Math.pow(2, 63) - 1.
В яваскрипте у Number точность целых чисел гораздо ниже:
9007199254740991 = Number.MAX_SAFE_INTEGER = Math.pow(2, 53) - 1
Строку она (MongoDB) отдаёт правильную а вот после парсинга вот что получается:
JSON.stringify(JSON.parse('{"a": 9223372036854775807}';
'{"a":9223372036854776000}'
В итоге у больших чисел теряется точность.

kill-still

Нагуглил, вот что:
1) конструктор всегда должен возвращать объект. Если из конструктора вызвать return 20;, то получаются очень интересные вещи.
2) Конструктор Number вызванный как функция (через call, apply или просто без new) не создаёт новый объект, а просто приводит тип.
В итоге у меня получился такой грязный хак:

var BigNumberProto = Object.create(Number.prototype);
BigNumberProto.myMethod = function {
return 'bla-bla';
};
function BigNumber(a) {
var n = new Number(a);
n.__proto__ = BigNumberProto;
return n;
}

Оно работает:
new BigNumber(27) + new BigNumber('31')
58

istran

Чем не нравятся варианты:
1) Считать все на сервере, в JS хранить строки.
2) Использовать готовую JS библиотеку для работы с big integer.

kill-still

всё и так на сервере.
потому что это совсем не то, что надо.

istran

Зачем тогда на клиенте нужно хранить числа в числовых типах?

Bibi

слова "все и так на сервере" в наши дни могут обозначать джаваскрипт на сервере

istran

Тогда второй пункт должен подойти.

agaaaa

Старайтесь по возможности предпочитать композицию наследованию.

kill-still

в js в принципе нет наследования. :grin:
Оставить комментарий
Имя или ник:
Комментарий: