3

Math 对象没有原型属性,但有构造函数属性。在任何情况下重新定义构造函数会有用吗?

4

8 回答 8

6

对象(准确地说: ECMAScript 全局对象的属性的初始值所指的对象)没有属性Math,请参阅ECMAScript语言规范,5.1 版,第 15.8 节“数学对象”。所以,Mathconstructor

Math.hasOwnProperty("constructor")

返回false(在符合 ECMAScript Ed. 3 及更高版本的实现中)。

Math对象通过原型链从其原型中继承一个constructor属性,即“标准内置Object原型对象(15.2.4)”(同上),与该Object.prototype属性最初所指的相同。后一个对象提供了几个有用的属性,例如Object.prototype.hasOwnProperty(见上文)。所以Math对象的原型链不为空是有道理的。

Math对象也继承只是 ECMAScript 实现中无条件继承的Object.prototype.constructor副作用(除了第 4 版提案的实现,也许还有未来的版本)属性没有合适的可见性修饰符来防止这种情况(比如private在几种基于类的语言中)。当然,继承自同一个原型的实例的构造函数,就是全局对象Object的属性初始值所引用的对象。Object所以Object.prototype.constructor必须反映这一点。因此,评估结果

Math.constructor === Object

true

于 2012-05-07T15:43:20.657 回答
5

所有对象都有一个constructor属性,该属性指示创建该对象的构造函数。

甚至({}).constructor回报Object()

于 2012-04-26T18:35:54.790 回答
3

实际上,Math 没有自己的“构造函数”属性。它从 Object.prototype 继承“构造函数”,就像它继承“toString”、“hasOwnProperty”和 Object.prototype 的所有其他属性一样。

对于数学,“构造”可能没有什么用处。它只是 JavaScript 继承工作方式的结果。

于 2012-04-27T15:10:09.437 回答
2

MDN说:

与其他全局对象不同,Math 不是构造函数。Math 的所有属性和方法都是静态的。

在其他语言中,当类是静态的时,您可以直接使用其属性和方法,而无需创建该类的实例(对象)。如果使用 Math 构造函数,则没有原生类型来支持对象,这与原始类型不同:Number、String、Boolean。它们可以使用包装器转换为对象。

此外,扩展根对象是一种不好的做法。如果将来在环境中实现了新功能并且代码没有对此进行故障安全检查,它将覆盖本机功能。

我个人的看法是,你不需要构造函数,也不需要原型——你可以定义自己的数学函数。Math 对象在这里只是为了呈现一个标准函数,并让程序员可以不定义Pior E,例如。并且可能用户定义的数学函数将比内置函数慢几倍。

于 2012-05-03T12:23:57.150 回答
2

Math对象“继承”自Object(意思Math.__proto__ === Object.prototype

对于Math任何 JavaScript 程序员来说,对象只不过是一个“特殊”但简单Object的附加方法,其实现和构造是自动和隐藏的。

Object.prototype定义一个.constructor字段(实际上任何函数都将自己分配给自己原型的构造函数,请参见ex1

ex1(有点绕道)

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

因此,当您使用 时Math.constructor,它只是像这样查找Math对象的原型链(......好吧):

  1. Math-->Math.hasOwnProperty('constructor')=== false

  2. 没有找到下一步

  3. Math.__proto__-->Math.__proto__.hasOwnProperty('constructor')=== true

  4. 找到,返回: Math.__proto__.constructor

所以基本上:

Math.constructor === Object.prototype.constructor; // true
// and as such:
Math.constructor === Object; // true
// and as stated at the top:
Math.__proto__ === Object.prototype; // true

希望这会有所帮助-ck

于 2012-05-07T19:29:28.853 回答
0

在我看来,JavaScript 中的 Math 对象试图模拟其他流行编程语言(例如 Java)中的静态数学行为。由于这只能在 JavaScript 中模拟,并且默认情况下所有对象都具有原型和构造函数属性,我的猜测是开发人员只是忘记将构造函数属性设置为undefined,通过显式执行类似Math.constructor = undefined;

于 2012-05-07T13:57:26.073 回答
0

在您需要在不污染全局范围的情况下生成转换表的情况下,这将很有用。例如:

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;
    }    
  }

调用构造函数来填充它:

Math.constructor();

Math.constructor["a"]

另一个用途是扩展属性和方法以定义图形库的原语:

root(arg,index) "index-th" 参数的根。示例:root(x,6) x 的第六个根,root[tan(x),4] x 的切线的第四个根。
sqrt() 参数的平方根(括号内的数字或表达式)。等价于根(参数,2)
cbrt() 参数的立方根。相当于根(参数,3)
logn(arg,base) 以 arg 为底的对数。
ln() 参数的自然对数(以 E 为底的参数对数,其中 E 是欧拉常数)
lg() 参数以 10 为底的对数,等价于 logn(argument,10)。
lb() 参数的以 2 为底的对数。
exp() 指数函数 E 的参数幂,等价于 E^argument
sin() 参数正弦
cos() 余弦
tan() 正切
cot() 余切
sec() 参数的割线,等价。为 1/cos(arg)。
csc() 余割,等效。为 1/sin(arg)。
asin() 反正弦
acos() 反余弦
atan() 反正切
acot() 反正切
asec() 弧正割,反割。
acsc() 反余割,反余割。
sinh() 双曲正弦,双曲正弦
cosh() 双曲余弦,双曲余弦
tanh() 双曲正切,Tangens hyperbolicus
coth() 双曲余切,双曲余切
sech() 双曲正割,双曲正割。
csch() 双曲余割,双曲余割。
asinh() 面积正弦,面积正弦双曲线,逆 sinh()。
acosh() 面积余弦,面积余弦双曲线,逆 cosh()。
atanh() 面积正切,面积正切双曲线,逆 tanh()。
acoth() 面积余切,双曲线余切面积,逆 cotanh()。
asech() 面积正割,双曲线面积正割,逆 sech()。
acsch() 面积余割,双曲线面积余割,逆 csch()。
gaussd(x,mean,sigma) 高斯分布(“钟形曲线”)。顺便说一下,gaussd(x,0,1) 是特例“正态分布密度,平均值=0,标准差=1”。
min(arg1,arg2) 返回两个参数中较小的一个
max(arg1,arg2) 返回两个参数中的较大者
round() 将参数向上或向下舍入到最接近的整数
floor() 向下舍入 arg。
ceil() 向上舍入 arg。
abs() 或 | | 参数的绝对值。示例:2abs(sin[x]) 或 2|sin(x)| .
sgn() 符号函数。
rand 0 和 1 之间的随机数。示例:
pi*rand*sin(x) 甚至 Pirandsin(x) 。
E 欧拉常数 2.718281828459045...
LN2 2的自然对数,是0.6931471805599453...
LN10 10的自然对数,是2.302585092994046...
LOG2E E 的以 2 为底的对数(E:见上文),为 1.4426950408889633...
LOG10E E 的以 10 为底的对数,是 0.4342944819032518...
PHI 黄金比例 1.61803398874989...
PI 3.141592653589793...
SQRT1_2 1/2 的平方根,为 0.7071067811865476...
SQRT2 2 的平方根,是 1.4142135623730951...

参考

于 2014-07-15T01:12:53.147 回答
-1
   <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>

粗略的你也可以这样做:

Math.rand=function(min,max){
    return Math.floor((Math.random() * (max-min+1))+min)
}

Math 没有像 Array 和 String 这样的原型的原因是它不是一个函数而是一个对象。因为你可以使用 newString()和 newArray()你也可以使用String.prototypeand Array.prototype

也是如此Object, Function, Number, Date, RegExp and even Boolean。但是,任何定义的函数都将被分配一个原型属性,并将继承自 Function 以及它必须继承的链中的任何其他内容。

如果你想像函数一样对待Math,你所要做的就是用函数覆盖变量。这种方式Math.constructor在调用时不会返回 Object ,因为它实际上会链接到创建它的用户定义函数。

您可以先制作本机对象的副本,然后将其扔给覆盖函数的原型属性之一,或者使用封装,以便只有您的新数学函数可以访问本机方法。不知道在这个问题上还能说什么。

开头的问题有点无意义。Math.constructor 将返回 Object 并且与直接调用 Object 相同。唯一的区别是如果您更改了构造函数。

你为什么要改变构造函数呢?

Math对象完全没有问题。如果我们期望它从某个地方继承某些东西,那么我们期望 " this" 指向什么?如果你能想出这个问题的答案,你就会有一些可以编码的目的。

于 2012-05-03T20:36:28.623 回答