DontEnum ]DontEnum ]
]
All of the built-in classes (except Math have a prototype
{ DontEnum, DontDelete, ReadOnly }.
New properties that are added to a built-in's prototype will be
exposed in a for in loop
of that object, or objects that appear further down the prototype chain.
On the other hand, replacing a property's value does not remove the
attributes from the property (§ 8.6.2.2).
For example, providing a replacement value for a method
that does not function properly, such as Number.prototype.toFixed().
(function(){ var n = .07, m = 1.1255; return n.toFixed(1) + ", " + m.toFixed(3); })();
0.1, 1.126| Browser: | Internet Explorer | Mozilla | Opera | Safari 2 | Safari 3 |
|---|---|---|---|---|---|
| Result: | 0.0, 1.126 | 0.1, 1.125 | 0.1, 1.125 | 1, 1.125 | 0.1, 1.126 |
Safari 3 is the only browser to provide a correct result for toFixed.
Replacing the value of an object instance's property with a user-defined toFixed will not
change the DontEnum attribute on that property (§ 8.6.2.2).
Number.prototype.toFixed
ECMAScript's Number.prototype.toFixed(fractionDigits) (§15.7.4.5).
Is buggy in all browsers except Safari 3.
It is possible to patch the buggy behavior with a replacement and also provide an expanded
range to Safari 3 without affecting the DontEnum flag.
The source code of the patch is in the head
of the document.
Replacing the value of
toFixed won't make the function enumerable.
(function(){ if(!Number.originalToFixed) Number.originalToFixed = Number.prototype.toFixed; // Check before adding the patch. var needsFix = Number.prototype.toFixed != fixedToFixed && ((.07).toFixed(1) != 0.1 || (1.1255).toFixed( 3 ) != 1.126 ); try { // We want also to expand the range. (.1).toFixed(-20); (.1).toFixed(100); } catch(e) { needsFix = true; } if(needsFix) { Number.prototype.toFixed = fixedToFixed; // fixedToFixed is in external js. } var origEl = document.getElementById("toFixed-fixed-orig"); var origResults = generateResults( Number.originalToFixed ); setTextContent(origEl, origResults); if(Number.prototype.toFixed !== Number.originalToFixed) { // We didn't create an enumerable property, or we'd see an alert. for(var prop in .07) { alert('failure: ' + prop); } document.getElementById("toFixed-fixed-result").style.border = "1px solid #F84"; origEl.className = "error"; } /* Takes either toFixed or originalToFixed. */ function generateResults( toFixedFunction ) { var result = Array(5); var argsArray = [ [9, -1] ,[.07, 1] ,[-.07, 1] ,[1.1255, 3] ,[1.1255,17] ]; for(var i = 0; i < argsArray.length; i++) { var args = argsArray[ i ]; try { result[i] = ( toFixedFunction.call( args[0], args[1]) ); } catch(e) { result[i] = ( e.name ); } } return result.join(String.nl); } var results = generateResults( Number.prototype.toFixed ); // Put it back the way it was before. Number.prototype.toFixed = Number.originalToFixed; return results; })();
| Result | Expected | Original |
|---|---|---|
10 0.1 -0.1 1.126 1.12550000000000000 |
| Browser: | Internet Explorer | Mozilla | Opera | Safari 2 | Safari 3 |
|---|---|---|---|---|---|
| Result: | 10 0.1 -0.1 1.126 1.12550000000000000 | 10 0.1 -0.1 1.126 1.12550000000000000 | 10 0.1 -0.1 1.126 1.12550000000000000 | RangeError .1 -.1 1.125 1.12550000000000000 | 10 0.1 -0.1 1.126 1.12550000000000000 |
| Original | RangeError 0.0 -0.0 1.126 1.12550000000000000 | RangeError 0.1 -0.1 1.125 1.12549999999999994 | RangeError 0.1 -0.1 1.125 1.12549999999999994 | RangeError .1 -.1 1.125 1.12550000000000000 | RangeError 0.1 -0.1 1.126 1.12550000000000000 |
We can see that enumerating through a number object did not cause "toFixed" to show up in the loop.
(Just in case any toolkit vendors want to enumerate over number primitives). link to blog entry
In IE, .07 and -.07 originally returned 0.0 and -0.0,
respectively.
Mozilla and Opera had rounding errors with (1.1255).toFixed(3). Mozilla and opera also have problems with (1.1255).toFixed(17), losing precision.
Safari 2 got the wrong result with (1.1255).toFixed(3), but got the correct result with (1.1255).toFixed(17). For .07, Safari 2 returns .1, but should instead return 0.1.
Only Safari 3 got it right the first time. The RangeError it throws on a negative
fractionDigits is perfectly valid.
Aside from fixing the bugs in the other browsers, this patch enhances toFixed with a greater precision. This is permitted
by the specification.
An implementation is permitted to extend the behaviour of toFixed for values of fractionDigits less than 0 or greater than 20. In this case toFixed would not necessarily throw RangeError for such values.
Next in this tutorial: ES4 Recommendations, Summary