Search code examples
javascriptextend

Extending Math object in JavaScript


Since it's bad practise extending built-in objects directly, I was thinking about creating a local object that extends the global one, e.g. with $.extend(obj, Math). Math is an object, however you can't seem to access any of its properties like this:

for (obj in Math) {
   console.log(obj);
}

Why?


Solution

  • Because they're all defined as non-enumerable. Almost all built-in properties of the specification-defined objects are non-enumerable. Non-enumerable properties don't show up when you enumerate the properties in the object (via for-in or Object.keys).

    Two ideas for you, though:

    1. You can create your object with Math as its prototype, like this:

       // Create the MyMath object with Math as its prototype
       var MyMath = Object.create(Math);
      
       // Check that MyMath has a Math function on it
       display(MyMath.floor(2.3));
      
       // Utility function
       function display(msg) {
           document.body.insertAdjacentHTML("beforeend", "<p>" + msg + "</p>");
       }
       

    2. ES5 introduced a new function, Object.getOwnPropertyNames, which can get the names of all properties (both enumerable and non-enumerable) from an object. (And since the prototype of Math is Object.prototype, you probably do just want the "own" properties.) So you could do this on an ES5-compliant engine:

      // Create the MyMath object with all of the own properties on Math
      var MyMath = {};
      Object.getOwnPropertyNames(Math).forEach(function(name) {
          MyMath[name] = Math[name];
      });
      
      // Check that MyMath has a Math function on it
      display(MyMath.floor(2.3));
      
      // Utility function
      function display(msg) {
          document.body.insertAdjacentHTML("beforeend", "<p>" + msg + "</p>");
      }

    Option 1 is probably your better option, not least because the single-argument version of Object.create can be shimmed/polyfilled on pre-ES5 engines.