The Math object does not have a prototype property, but does have a constructor property. Is there any case in which redefining the constructor would be useful?
MDN says:
Unlike the other global objects, Math is not a constructor. All properties and methods of Math are static.
In other languages, when a class is static, you can directly use its properties and methods without creating an instance of that class ( an object ). If Math constructor is used, there is no native type to support the object, unlike with the primitive types: Number, String, Boolean. They can be converted to objects with their wrappers.
Furthermore it is a bad practice to extend a root object. If in the future new functionality is implemented in the environment and the code don't have fail-safety check for this, it will override the native one.
My personal opinion is that you do not constructor, nor prototype - you can define your own mathematical functions. The Math object is here just to present a standard functions, and give programmers the leverage not to define Pi
or E
, for example. And probably user defined mathematical function will be several times slower than the built-in.
The Math
object (precisely: the object referred to by the initial value of the Math
property of the ECMAScript Global Object) does not have a constructor
property, see the ECMAScript Language Specification, 5.1 Edition, section 15.8 "The Math Object". Therefore,
Math.hasOwnProperty("constructor")
returns false
(in conforming implementations of ECMAScript Ed. 3 and later).
The Math
object inherits a constructor
property through the prototype chain from its prototype, which is "the standard built-in Object prototype
object (15.2.4)" (ibid.), which is the same as initially referred to by the Object.prototype
property. The latter object provides several useful properties, such as Object.prototype.hasOwnProperty
(see above). So it makes sense that the prototype chain of the Math
object is not empty instead.
That the Math
object also inherits Object.prototype.constructor
is merely a side-effect of that unconditional inheritance in ECMAScript implementations as (with the exception of implementations of the Edition 4 proposal, and perhaps of future Editions) properties do not have a suitable visibility modifier to prevent that (like private
in several class-based languages). And, of course, the constructor of Object
instances, which inherit from the same prototype, is the object referred to by the initial value of the Object
property of the Global Object. So Object.prototype.constructor
must reflect that. Therefore, the result of evaluating
Math.constructor === Object
is true
.
All objects have a constructor
property, which indicates the constructor that created the object.
Even ({}).constructor
returns Object()
.
Actually, Math does not have its own "constructor" property. It inherits "constructor" from Object.prototype, just like it inherits "toString", "hasOwnProperty" and all of the other properties of Object.prototype.
For Math, "construct" probably has very little utility. It is just there as a consequence of how JavaScript inheritance works,.
Math
object "inherits" from Object
(meaning Math.__proto__ === Object.prototype
)
The Math
object is nothing more to any JavaScript programmer than a "special" but simple Object
with methods attached whose implementation and construction is automatic and hidden.
Object.prototype
defines a .constructor
field (actually any function assigns itself to its own prototype's constructor, see ex1)
ex1 (a little bit of a detour):
function xxx() { }
// then:
xxx.prototype.constructor === xxx; // true
// since xxx is a function:
xxx.constructor === Function.prototype.constructor; // true
// and as such:
xxx.constructor === Function; // true
As such when you use Math.constructor
, it's just looking up the Math
object's prototypical chain like this (...well kind of):
Math
--> Math.hasOwnProperty('constructor')
=== false
NOT FOUND MOVE NEXT
Math.__proto__
--> Math.__proto__.hasOwnProperty('constructor')
=== true
FOUND, RETURN: Math.__proto__.constructor
so basically:
Math.constructor === Object.prototype.constructor; // true
// and as such:
Math.constructor === Object; // true
// and as stated at the top:
Math.__proto__ === Object.prototype; // true
hope this helps -ck
In my opinion the Math object in JavaScript tries to simulate the static Math behavior in other popular programming languages (for example Java). Since this can only be simulated in JavaScript, and all Objects have prototype and constructor properties by default, my guess is that the developers have just forgotten to set the constructor property to undefined
, by executing explicitly something like Math.constructor = undefined;
In a situation in which you need to generate a conversion table without polluting the global scope, this would be useful. For example:
Math.constructor = function() {
var i = 0, unicode = {}, zero_padding = "0000", max = 9999;
//Loop through code points
while (i < max) {
//Convert decimal to hex value, find the character, then pad zeroes to the codepoint
Math.constructor[String.fromCharCode(parseInt(i, 16))] = ("u" + zero_padding + i).substr(-4);
i = i + 1;
}
}
Invoke the constructor to populate it as such:
Math.constructor();
Math.constructor["a"]
Another use would be to extend the properties and methods to define primitives for a graph library:
root(arg,index) "index-th" root of argument. Example: root(x,6) sixth root of x, root[tan(x),4] fourth root of the tangent of x. sqrt() Square root of argument (number or expression inside the parentheses). Equivalent to root(argument,2) cbrt() Cube root of argument. Equivalent to root(argument,3) logn(arg,base) Logarithm base-base of arg. ln() Natural logarithm of argument (base-E logarithm of argument where E is Euler's constant) lg() Logarithm base-10 of argument, equivalent to logn(argument,10). lb() Logarithm base-2 of argument. exp() Exponential Function E to the power of argument, equivalent to E^argument sin() Sine of argument cos() Cosine tan() Tangent cot() Cotangent sec() Secant of argument, equiv. to 1/cos(arg). csc() Cosecant, equiv. to 1/sin(arg). asin() Arc sine acos() Arc cosine atan() Arc tangent acot() Arc cotangent asec() Arc secant, inverse secant. acsc() Arc cosecant, inverse cosecant. sinh() Hyperbolic sine, Sinus hyperbolicus cosh() Hyperbolic cosine, Cosinus hyperbolicus tanh() Hyperbolic tangent, Tangens hyperbolicus coth() Hyperbolic cotangent, Cotangens hyperbolicus sech() Hyperbolic secant, Secans hyperbolicus. csch() Hyperbolic cosecant, Cosecans hyperbolicus. asinh() Area sine, Area sinus hyperbolicus, inverse sinh(). acosh() Area cosine, Area cosinus hyperbolicus, inverse cosh(). atanh() Area tangent, Area tangens hyperbolicus, inverse tanh(). acoth() Area cotangent, Area cotangens hyperbolicus, inverse cotanh(). asech() Area- secant, Area secans hyperbolicus, inverse sech(). acsch() Area- cosecant, Area cosecans hyperbolicus, inverse csch(). gaussd(x,mean,sigma) Gaussian distribution ("Bell Curve"). gaussd(x,0,1), by the way, is the special case "Normal distribution density with mean-value=0, standard-deviation=1". min(arg1,arg2) Returns the lesser of the two arguments max(arg1,arg2) Returns the greater of the two arguments round() Rounds argument up or down to the closest integer floor() Rounds arg down. ceil() Rounds arg up. abs() or | | Absolute value of argument. Example: 2abs(sin[x]) or alternatively 2|sin(x)| . sgn() Sign Function.
rand Random number between 0 und 1. Example: pi*rand*sin(x) or even Pirandsin(x) . E Euler's constant 2.718281828459045... LN2 Natural logarithm of 2, is 0.6931471805599453... LN10 Natural logarithm of 10, is 2.302585092994046... LOG2E Base-2 logarithm of E (E: see above), is 1.4426950408889633... LOG10E Base-10 logarithmus of E, is 0.4342944819032518... PHI Golden Ratio 1.61803398874989... PI 3.141592653589793... SQRT1_2 Square root of 1/2, is 0.7071067811865476... SQRT2 Square root of 2, is 1.4142135623730951...
References
<script type="text/javascript">
Math.prototype=Math;
Math.prototype.rand=function(min,max){
return Math.floor((Math.random() * (max-min+1))+min)
}
var o=[];
for(var i=0;i<100;i++)o.push(Math.rand(-1,1));
alert(o.join(", "))
</script>
Of coarse you could also just do:
Math.rand=function(min,max){
return Math.floor((Math.random() * (max-min+1))+min)
}
The reason Math doesn't come with its own prototype like Array and String is because it isn't a function but rather an object. Since you can use new String()
and new Array()
you are also able to use String.prototype
and Array.prototype
.
The same goes for Object, Function, Number, Date, RegExp and even Boolean
. However any defined function will be assigned a prototype property and will inherit from Function and whatever else in the chain it has to inherit from.
If you want to treat Math
like a function, all you have to do is override the variable with a function. That way Math.constructor
will not return Object when called since it would actually be linked to your user-defined function that created it.
You can make a copy of the native object first then toss it to one of the prototype properties of your overriding function, or use encapsulation so only your new Math function can access the native methods. Not sure what else can be said on the subject.
The opening question is kind of pointless. Math.constructor will return Object and will be the same as calling Object directly. The only difference would be if you changed the constructor.
Why would you want to change the constructor anyways?
The Math
object is perfectly fine the way it is. If we expected it to inherit something from somewhere, what would we expect "this
" to point to anyways? If you can come up with an answer to that question, you will have something with a purpose you can code.
©2020 All rights reserved.