MikeMcl / bignumber.js

A JavaScript library for arbitrary-precision decimal and non-decimal arithmetic
http://mikemcl.github.io/bignumber.js
MIT License
6.66k stars 742 forks source link

Revive BigNumber from being serialized to plain object #245

Open ralekna opened 5 years ago

ralekna commented 5 years ago

Hi,

there are some occasions when BigNumber is converted to plain object and loses BigNUmber prototype - for example when it is taken from window.history.state. In such situation it's a bit uncomfortable to make such object fully functional again. For example

BigNumber.prototype.toFormat.call({"s":1,"e":3,"c":[8212,89000000000000]})

will raise an exception TypeError: x.toFixed is not a function because toFormat function assumes that this object is "normal" BigNumber instance.

Trying to pass that object to constructor also fails:

new BigNumber({"s":1,"e":3,"c":[8212,89000000000000]}).toFormat(); // NaN

My suggestion (and feature request) would be to introduce static .from() method or modify constructor to accept such object.

Regards

MikeMcl commented 5 years ago

An _isBigNumber property is required, so:

BigNumber.prototype.toFormat.call(
  new BigNumber({"s":1,"e":3,"c":[8212,89000000000000], _isBigNumber: true})
);
// "8,212.89"
new BigNumber({"s":1,"e":3,"c":[8212,89000000000000], _isBigNumber: true}).toFormat();
// "8,212.89"

I don't think that the vast majority of users will want to be creating BigNumbers in this way and it is not something I want to encourage, so I am reluctant to add another method to the API.

I only added this ability when requested becuase it was basically very simple and costless to do so.

ralekna commented 5 years ago

Hi Michael,

thanks for a such quick reply! I didn't know about that _isBigNumber property as it is not passed to serialized object (from source is see it's in prototype - not own property). I'll add it before trying to deserialize but IMO (if it doesn't affect performance tragically) recognition of of such plain object could be done by object used properties ({c, e, s}) instead of embedding this single purpose prop. Thanks anyway - this saved a lot time for me :)

Regards, Rytis

F3n67u commented 3 years ago

@MikeMcl BigNumber is converted to plain object and loses BigNumber prototype when window.postMessage,any solution to this occasion?

ralekna commented 3 years ago

@F3n67u same solution because the problem is same.

MikeMcl commented 3 years ago

@F3n67u

Post the BigNumber constructor along with the BigNumbers, then you can use the method shown above, or Object.create or Object.setPrototypeOf or such like.

F3n67u commented 3 years ago

@ralekna @MikeMcl I use Native BigInt to solve the problem, bec window.postMessage support pass BigInt without lose it's type.

In the occasion which require demical divide, I still use Big.js:

export function toBigIntNs(seconds: number): bigint {
  return BigInt(new Big(seconds).times(1e9).round().toString());
}