I needed a function to generate a pseudo-random integer between m and n, and so I thought, “I know, I’ll extend Math with a randrange method, similar to Python’s”.
Math.constructor.prototype.rand = function rand(min, max) {
return min + Math.floor(Math.random() * (max + 1 - min));
};
This seems to work, but when I put it into my integrated code, I experienced multiple problems with error messages like “[that function] has no method ‘addEventListener'”.
The gist of my question is this: Is there something fundamentally wrong with the way I’ve extended Math here? Should that function have such a method, and if not, why is jwplayer asking for it?
I’ve attached much more detail below, but if you’re already bored and want to start postulating answers, you can skip the rest.
When I went to test the integrated code I saw this error:
jwplayer.js:1 Uncaught TypeError: Object function rand(min, max) {
return min + Math.floor(Math.random() * (max + 1 - min));
} has no method 'addEventListener'
jwplayer.js:1 a.plugins.pluginloader.load
jwplayer.js:1 a.embed
jwplayer.js:1 b.api.setup
script.js:155 (anonymous function)
jquery-1.6.4.js:660 jQuery.extend.each
jquery-1.6.4.js:274 jQuery.fn.jQuery.each
script.js:150 jQuery.click.window.Modernizr.input.required
jquery-1.6.4.js:1016 jQuery.extend._Deferred.deferred.resolveWith
jquery-1.6.4.js:437 jQuery.extend.ready
jquery-1.6.4.js:923 DOMContentLoaded
Here’s a snippet from script.js that the above refers to:
// Setup the video player:
$("video").each(function (i, e) {
// Switching out ids like this is a horrible hack,
// but apparently it's the only way jwplayer will load.
var oldId = $(e).attr('id');
$(e).attr("id", "tmpVideoSetup");
jwplayer("tmpVideoSetup").setup({
flashplayer: window.CDN + "/js/libs/mediaplayer-5.7-licensed/player.swf",
levels: [
// TODO: set this up to dynamically choose the videos to play.
{ file: window.CDN + "/videos/LK_About.mp4" },
{ file: window.CDN + "/videos/LK_About.wmv" }
]
});
$(e).attr("id", oldId);
});
When I remove the video-loading code, everything else behaves as expected.
Why attach it to
Mathat all? And if you’re going to, what’s wrong withMath.rand = ...?The
MathObject isn’t supposed to be extended in a prototypal manner, because it’s a “static” type. You cannot instantiate it (i.e. call it withnew). This is an exceptional case. All other types are “non-static”. Although that shouldn’t be surprising,Mathis simply a collection of static methods. There is no need for any instantiation.Math.constructor === Object(at least in chrome), so you’re actually extending every object’s prototype, and presumably the other library is enumerating over all object properties. For example: