通过原型扩展Math对象不起作用

时间:2014-12-20 13:56:08

标签: javascript math prototype built-in

我尝试扩展JavaScript Math。但有一件事让我感到惊讶。

当我尝试按prototype

扩展它时
Math.prototype.randomBetween = function (a, b) {
    return Math.floor(Math.random() * (b - a + 1) + a);
};

在控制台中我有错误'无法设置属性' randomBetween'未定义的' ...

但是,如果我将此功能赋予Math.__proto__

Math.__proto__.randomBetween = function (a, b) {
    return Math.floor(Math.random() * (b - a + 1) + a);
};

然后一切正常。

任何人都能解释一下为什么它以这种方式运作吗?我感谢任何帮助。

4 个答案:

答案 0 :(得分:30)

Math不是构造函数,因此它没有prototype属性:

new Math(); // TypeError: Math is not a constructor

相反,只需将您的方法添加到Math本身作为own property

Math.randomBetween = function (a, b) {
    return Math.floor(Math.random() * (b - a + 1) + a);
};

使用__proto__的方法有效,因为MathObject个实例,Math.__proto__Object.prototype

但请注意,您正在向所有对象添加randomBetween方法,而不仅仅是Math。这可能会有问题,例如在使用for...in循环迭代对象时。

答案 1 :(得分:3)

引用this answer

  

某些JavaScript实现允许直接访问[[Prototype]]属性,例如通过名为__proto__的非标准属性。通常,只能在对象创建期间设置对象的原型:如果通过新的Func()创建新对象,则将设置对象的[[Prototype]]属性到Func.prototype引用的对象。

您无法使用.prototype分配给原型的原因是因为Math对象已经创建。

幸运的是,我们可以通过简单地使用:

Math对象分配新属性
Math.myFunc = function() { return true };

在您的情况下,这将是:

Math.randomBetween = function(...) { ... };

答案 2 :(得分:1)

那是因为Math是一个对象,不是一个function

在javascript中,function是面向对象语言中类的粗略等价物。 prototype是一个特殊属性,允许您将实例方法添加到此类 1 。如果您想扩展该课程,可以使用prototype,而且#34;只是工作"。

现在让我们考虑Math是什么。你永远不会创建一个数学对象,你只需使用它的方法。事实上,创建两个不同的Math对象是没有意义的,因为Math总是有效!换句话说,javascript中的Math对象只是将一堆预先编写的数学相关函数组合在一起的便捷方式。它就像一本普通数学字典。

想要向该群组添加内容吗?只需在集合中添加属性即可!这是两种简单的方法。

Math.randomBetween = function() { ... }
Math["randomBetween"] = function() {... }

使用第二种方式使它更加明显,它是一个字典类型集合,但它们都做同样的事情。

答案 3 :(得分:0)

var MyMath = Object.create(Math); // empty object with prototype Math

MyMath.randomBetween = function (a, b) {
    return this.floor(this.random() * (b - a + 1) + a);
};

typeof(MyMath);                 // object
Object.getPrototypeOf(MyMath);  // Math
MyMath.PI;                      // 3.14...
MyMath.randomBetween(0, 10);    // exactly that
  • Math对象是新MyMath对象
  • 的原型
  • MyMath可以访问Math
  • 的所有功能
  • 您可以在不操纵MyMath
  • 的情况下将自定义功能添加到Math
  • 在您的自定义方法中,使用关键字this来引用Math功能

这种方法没有 Monkey Patching 。这是扩展JavScript Math的最佳方法。没有必要重复其他答案的解释。