通过原型扩展数学对象不起作用
Extending Math object through prototype doesn't work
我尝试扩展JavaScript Math
。但有一件事让我感到惊讶。
当我试图通过prototype
扩展它时
Math.prototype.randomBetween = function (a, b) {
return Math.floor(Math.random() * (b - a + 1) + a);
};
在控制台中,我有错误"无法设置未定义的属性'随机之间'"...
但是如果我将此功能分配给Math.__proto__
Math.__proto__.randomBetween = function (a, b) {
return Math.floor(Math.random() * (b - a + 1) + a);
};
然后一切正常。
谁能解释我为什么它以这种方式工作?我感谢任何帮助。
Math
不是构造函数,因此它没有prototype
属性:
new Math(); // TypeError: Math is not a constructor
相反,只需将方法添加为将自身Math
为自己的属性:
Math.randomBetween = function (a, b) {
return Math.floor(Math.random() * (b - a + 1) + a);
};
您使用__proto__
的方法有效,因为由于Math
是一个Object
实例,因此Math.__proto__
Object.prototype
。
但请注意,您正在randomBetween
方法添加到所有对象,而不仅仅是Math
.这可能会有问题,例如,在使用 for...in
循环迭代对象时。
那是因为有一个对象Math
,而不是一个function
。
在javascript中,function
大致相当于面向对象语言中的类。 prototype
是一个特殊属性,允许您将实例方法添加到此类1。 当你想扩展该类时,你使用prototype
它"只是工作"。
现在让我们想想Math
是什么。 你永远不会创建一个数学对象,你只是使用它的方法。 事实上,创建两个不同的Math
对象是没有意义的,因为Math
总是相同的工作! 换句话说,javascript 中的 Math
对象只是将一堆预先编写的数学相关函数组合在一起的便捷方法。 这就像一本普通数学的字典。
想要向该组添加内容? 只需将属性添加到集合中即可! 这里有两种简单的方法可以做到这一点。
Math.randomBetween = function() { ... }
Math["randomBetween"] = function() {... }
使用第二种方式可以更明显地表明它是一个字典类型的集合,但它们都做同样的事情。
引用这个答案:
一些JavaScript实现允许直接访问[[Prototype]]属性,例如通过名为
__proto__
的非标准属性。通常,只能在对象创建期间设置对象的原型:如果通过 new Func(( 创建新对象,则对象的 [[Prototype]] 属性将设置为 Func.prototype 引用的对象。
无法使用 .prototype
分配给其原型的原因是Math
对象已创建。
幸运的是,我们可以通过简单地使用以下命令为 Math
对象分配新属性:
Math.myFunc = function() { return true };
在您的情况下,这将是:
Math.randomBetween = function(...) { ... };
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
功能
这种方法没有猴子补丁。这是扩展 JavScript Math
的最佳方式。没有必要重复其他答案的解释。
虽然Math
是一个实际的Object
而不是一个constructible class
但您可以使用spread operator: {...obj}
来扩展数学对象,如下所示:
const ExtendMath = {
...Math,
randomInt(max, min = 0){Math.floor(Math.random() * (max - min + 1)) + min},
}
现在,randomInt()
方法将作为扩展方法添加到Math
对象中。
- JavaScript参数对象不起作用
- Javascript敲除绑定嵌套对象不起作用
- 反应.js - 处于异步数据状态的深层对象不起作用
- 为什么这个对象不起作用
- KnockoutJS - 创建对象不起作用
- Javascript 如果元素不存在返回,则导致对象不起作用
- 通过指令范围传递对象不起作用
- 通过原型扩展数学对象不起作用
- Concat 对象不起作用,或者我需要将值转换为正确的格式
- 使用速记检查未定义的对象不起作用
- 将信息从表单值推送到对象不起作用
- 淘汰:在对象不起作用的情况下进行多选
- 解析函数对Node.js中的promise对象不起作用
- Angularjs指令隔离了对象不起作用的范围+单向数据绑定
- Mongoose - find():搜索选项中的对象不起作用
- 在函数内部生成的对象不起作用,但是传入的对象起作用
- .focus()对克隆对象不起作用
- Ng-click对不透明度为1的对象不起作用
- Javascript对象不起作用
- 将绑定的数据推入对象不起作用