Share this Page URL

Chapter 21. Packaging Data and Functions... > Troubleshooting - Pg. 444

Packaging Data and Functions Using Custom Objects 444 Hijacking the Math Object Generally, you cannot change the values of the built-in properties of global objects. This could be inconvenient. Suppose you have a program that uses a lot of Math functions involving integers, and you want to change its "precision" so that you round to the nearest tenth instead of the nearest integer. You could add several new methods to the Math object that round to the nearest tenth. Then you would have to change all the Math method references in the program. How much simpler life would be if you could just change the functions in the Math object! A workaround accomplishes this goal. It takes advantage of the fact that the Math object is a property of the top-level Object. It involves "hijacking" the Math property name and pointing it at an object that you have created using the new operator. Here's the code: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: x = 10.21 trace("1 : "+Math.floor(x)); // "10" -- calls the original myMath = new Object(); myMath.__proto__ = Math; myMath.oldFloor = Math.floor; myMath.floor = function (arg) { arg *= 10; var result = myMath.oldFloor (arg); return result/10; } Object.prototype.Math = myMath; trace("2 : "+Math.floor(x)); // "10.2" - calls the custom property First, you create a new object (line 3). Then you use __proto__ to make your new object look in the Math object whenever it can't find a referenced property locally (line 4). This step is important because the "real" Math object is going to be "hidden" behind your object, and will not be accessible in any way other than via this __proto__ link. If you want to add a new property and still be able to access the old property as well, create a property in your new object that points at the old property (line 5). Now create your new math function (lines 6­10). The "crime" takes place on line 11. Here, you "steal" the name "Math" in the Object.prototype and point it at your new object. That's it. Line 12 just proves that this procedure worked: Math.floor() now rounds to one decimal place, unlike line 2, where it rounded to an integer. Troubleshooting Why can't I override my get/set methods? It's not you! It's them ! When you use addProperty() in the normal way, the getter/setter functions cannot be overridden. For instance, suppose you have a statement like this: function MyClass () { this.addProperty("myProp", MyClass.prototype.getMyProp, MyClass.prototype.setMyProp); } MyClass.prototype.getMyProp() and MyClass.prototype.setMyProp() will be execu- ted when myProp is read or written, respectively. Now you create a subclass with methods with those same names in its prototype: function MySubClass () {} MySubClass.prototype = new MyClass(); MySubClass.prototype.getMyProp = function () { // statements