Of these similar function definitions, what is optimal way to access arguments and why?
function DoStuff()
{
return arguments[0] + arguments[1] + arguments[2];
}
function DoStuff(first, second, third)
{
return first + second + third;
}
Does one allocate less memory than the other? Is one faster to access the parameter values than the other?
Here is my test:
function Test1()
{
var start = new Date();
for (var i = 0; i < 1000000; i++)
{
DoStuff1(i, i + 1, i + 2);
}
var done = new Date();
alert(done - start);
}
function Test2()
{
var start = new Date();
for (var i = 0; i < 1000000; i++)
{
DoStuff2(i, i + 1, i + 2);
}
var done = new Date();
alert(done - start);
}
function DoStuff1()
{
var result = arguments[0] + arguments[1] + arguments[2];
}
function DoStuff2(first, second, third)
{
var result = first + second + third;
}
Here are the results:
IE FF
Test1()
2355 402
2381 395
2368 392
Test2()
504 6
507 7
505 7
I figured that test 2 would be faster but it's drastically faster. So, not only is it more readable but it's more efficient.
Forget about performance in this case and go for readability. From that perspective, option (2) is much to be preferred -- though, I'd go for more descriptive names. ;-)
The second.
Using the second, you know based on the signature exactly what is expected when you call the method. It's also far easier for maintainability in the future.
Referencing arguments[] anywhere in a function will significantly decrease performance on many browsers.
The performance difference should be fairly negligible between the two, however the readability of named parameters is a better practice. There are times when you cannot use named parameters and in those cases I typically use a big block of script to unpack arguments into named locals.
Related
I want to understand the performance difference for constructing arrays. Running the following program, I am puzzled by the output below:
Time for range0: 521
Time for range1: 149
Time for range2: 1848
Time for range3: 8411
Time for range4: 3487
I don't understand why 3 takes longer than 4, while 1 takes shorter than 2. Also, seems the map function is very inefficient; what is the use of it?
function range0(start, count) {
var arr = [];
for (var i = 0; i < count; i++) {
arr.push(start + i);
}
return arr;
}
function range1(start, count) {
var arr = new Array(count);
for (var i = 0; i < count; i++) {
arr[i] = start + i;
}
return arr;
}
function range2(start, count) {
var arr = Array.apply(0, Array(count));
for (var i = 0; i < count; i++) {
arr[i] = start + i;
}
return arr;
}
function range3(start, count) {
var arr = new Array(count);
return arr.map(function(element, index) {
return index + start;
});
}
function range4(start, count) {
var arr = Array.apply(0, Array(count));
return arr.map(function(element, index) {
return index + start;
});
}
function profile(range) {
var iterations = 100000,
start = 0, count = 1000,
startTime, endTime, finalTime;
startTime = performance.now();
for (var i = 0; i < iterations; ++i) {
range(start, count);
}
endTime = performance.now();
finalTime = (endTime - startTime);
console.log(range.name + ': ' + finalTime + ' ms');
}
[range0, range1, range2, range3, range4].forEach(profile);
I don't understand why 3 takes longer than 4
Me neither. It is a surprising result, given my superficial analysis and the results I obtained by profiling the code. On my computer running Google Chrome 50, range4 is twice as slow compared to range3.
I'd have to study the Javascript implementation you are using in order to figure out why that happens.
while 1 takes shorter than 2.
range1 executes faster because it uses a loop and optimizes memory allocations, while range2 uses functions and does unnecessary memory allocations.
Also, seems the map function is very inefficient; what is the use of it?
The map function is used to compute a new Array based on the values of an existing one.
[1, 2, 3, 4, 5].map(number => number * number);
// [1, 4, 9, 16, 25]
On my computer
Time for range0: 783
Time for range1: 287
Time for range2: 10541
Time for range3: 14981
Time for range4: 28243
My results reflect my expectations regarding the performance of each function.
A superficial analysis of each function
range0
Creates an Array and populates it via a loop. It is the most simple and straightforward code possible. I suppose it could be understood as the baseline for performance comparison.
range1
Uses the Array constructor with a length parameter. This greatly optimizes the underlying memory allocation required to store the elements. Since the exact number of elements is known beforehand, the memory does not have to be reallocated as the number of elements grows; the exact amount of memory needed to store all elements can be allocated exactly once, when the Array is instantiated.
range2
Applies an empty arguments list to the constructor function, with this set to the number 0. This is semantically equivalent to Array() – the fact the arguments list was created with a count parameter has no bearing on the result of the function application. In fact, it needlessly wastes time allocating memory for an empty arguments list.
You probably meant to use call:
Array.call(null, count)
range3
Like range1, but uses map with a function instead of a loop. The initial memory allocation is optimized, but the overhead of calling the function count times is likely to be huge.
In addition, map generates a new Array instance. Since that instance also has count elements, it would make sense to optimize that memory allocation as well, however it is unclear to me whether that actually happens. Nevertheless, two separate memory allocations are taking place, instead of just one as in range1.
range4
Combines all the inefficiencies of range2 and range3.
Amazingly, it executes faster than range3 on your computer. It's unclear to me why that happened. I suppose one would have to investigate your Javascript particular implementation in order to figure it out.
I have got a homework where i am supposed to write a pseudo random number generator in JavaScript. This is the code bit i wrote
var k = 0;
var slump = function(n, k) {
if (k < 10) {
console.log("stop");
}
else {
k++;
console.log((5*n + 1) % 8);
return slump((5*n + 1) % 8, k);
}
};
slump(0);
k is supposed to hold the amount of times the function has been called. But instead of just running the function ten times, it just keeps running. Is there any way to get around this?
You have two subtly different options here, depending on how idiomatic and clever you'd like to get.
The classic implementation, with a slight tweak as JS doesn't support default parameters, would be to use something like:
var finalDepth = 0;
function slump(n, k) {
k = k || 0; // Set to 0 if falsy (null, undef, or 0)
if (logic) {
finalDepth = k; // Record the depth on the last call
} else {
return slump((5*n + 1) % 8, k + 1);
}
}
This will very simply record the deepest the stack has been, and hang onto the value until the next call.
If you want to be slightly more JS-like, you can use closure to keep track of the calls:
function createGenerator() {
var counter = 0;
return {
slump: function (n) {
++counter; // Closure captures counter, counter persists between slump calls but is unique for each createGenerator
if (logic) {
// stop
} else {
return slump((5*n + 1) % 8, k + 1);
}
},
getCounter: function () { return counter; }
}
}
You may be able to use some of the features from ES6 iterators (or generators) to make this more clever.
The function parameter k is uninitialized, therefore not a number. this means in particular that the termination test k < 10 fails as well as the k++ statement doesn't change k' s value. so slump gets always called with the same value for parameter k and the recursion never stops.
Whenever you write a recursive function, you need to make sure that:
There's a base case (in your case, when the console.log statement runs)
The function proceeds towards the base case, and
The function works, assuming the success of the recursive call.
You're running into a problem with the second part; you increment k, but that doesn't bring you any closer to the part where k < 10. In short, you probably want to switch that test around and make sure you're initially calling the function with the right number of arguments. (Aadit M Shah pointed out that you're calling it with one, and it expects two, meaning that it ends up undefined when you call it.)
Either way, iteration would definitely work better here:
var n = 0;
for(var i = 0; i < 10; i++) {
n = (5 * n + 1) % 8;
console.log(n);
}
This is the best way I can think of phrasing this question, given this JavaScript "class" definition:
var Quota = function(hours, minutes, seconds){
if (arguments.length === 3) {
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
this.totalMilliseconds = Math.floor((hours * 3600000)) + Math.floor((minutes * 60000)) + Math.floor((seconds * 1000));
}
else if (arguments.length === 1) {
this.totalMilliseconds = hours;
this.hours = Math.floor(this.totalMilliseconds / 3600000);
this.minutes = Math.floor((this.totalMilliseconds % 3600000) / 60000);
this.seconds = Math.floor(((this.totalMilliseconds % 3600000) % 60000) / 1000);
}
this.padL = function(val){
return (val.toString().length === 1) ? "0" + val : val;
};
this.toString = function(){
return this.padL(this.hours) + ":" + this.padL(this.minutes) + ":" + this.padL(this.seconds);
};
this.valueOf = function(){
return this.totalMilliseconds;
};
};
and the following test setup code:
var q1 = new Quota(23, 58, 50);
var q2 = new Quota(0, 1, 0);
var q3 = new Quota(0, 0, 10);
console.log("Quota 01 is " + q1.toString()); // Prints "Quota 01 is 23:58:50"
console.log("Quota 02 is " + q2.toString()); // Prints "Quota 02 is 00:01:00"
console.log("Quota 03 is " + q3.toString()); // Prints "Quota 03 is 00:00:10"
Is there any way of implicitly creating q4 as a Quota object using the addition operator as follows...
var q4 = q1 + q2 + q3;
console.log("Quota 04 is " + q4.toString()); // Prints "Quota 04 is 86400000"
rather than resorting to...
var q4 = new Quota(q1 + q2 + q3);
console.log("Quota 04 is " + q4.toString()); // Prints "Quota 04 is 24:00:00"
If not what are the best practice recommendations in this area for making custom numeric JavaScript objects composable via the arithmetic operators?
As far as I'm aware, Javascript (at least as it exists now) doesn't support operator overloading.
The best I can suggest is a class method for making new quota objects from several others. Here's a quick example of what I mean:
// define an example "class"
var NumClass = function(value){
this.value = value;
}
NumClass.prototype.toInteger = function(){
return this.value;
}
// Add a static method that creates a new object from several others
NumClass.createFromObjects = function(){
var newValue = 0;
for (var i=0; i<arguments.length; i++){
newValue += arguments[i].toInteger();
}
return new this(newValue)
}
and use it like:
var n1 = new NumClass(1);
var n2 = new NumClass(2);
var n3 = new NumClass(3);
var combined = NumClass.createFromObjects(n1, n2, n3);
Unfortunately no.
For fallbacks, if you arranged the return values, you could use method chaining
var q4 = q1.plus(p2).plus(q3);
Since everyone down voted my other answer I wanted to post proof of concept code which does in fact work as intended.
This has been tested in chrome and IE.
//Operator Overloading
var myClass = function () {
//Privates
var intValue = Number(0),
stringValue = String('');
//Publics
this.valueOf = function () {
if (this instanceof myClass) return intValue;
return stringValue;
}
this.cast = function (type, call) {
if (!type) return;
if (!call) return type.bind(this);
return call.bind(new type(this)).call(this);
}
}
//Derived class
var anotherClass = function () {
//Store the base reference
this.constructor = myClass.apply(this);
var myString = 'Test',
myInt = 1;
this.valueOf = function () {
if (this instanceof myClass) return myInt;
return myString;
}
}
//Tests
var test = new myClass(),
anotherTest = new anotherClass(),
composed = test + anotherTest,
yaComposed = test.cast(Number, function () {
return this + anotherTest
}),
yaCComposed = anotherTest.cast(Number, function () {
return this + test;
}),
t = test.cast(anotherClass, function () {
return this + anotherTest
}),
tt = anotherTest.cast(myClass, function () {
return this + test;
});
debugger;
If someone would be so kind as to give a technical explanation WHY this is not good enough I would be happy to hear it out!
Paper.js does it, for example with point addition (docs):
var point = new Point(5, 10);
var result = point + 20;
console.log(result); // {x: 25, y: 30}
But it does it using its own custom script parser.
You can implicitly convert to integer or string, your objects.
Objects are only implicitly converted if JavaScript expects a number or a string. In the former case, the conversion takes three steps:
1.- Call valueOf(). If the result is primitive (not an object) then use it and convert it to a number.
2.- Otherwise, call toString(). If the result is primitive, use it and convert it to a number.
3.- Otherwise, throw a TypeError.
Example for step 1:
3 * { valueOf: function () { return 5 } }
If JavaScript converts to string, steps 1 and 2 are swapped: toString() is tried first, valueOf() second.
http://www.2ality.com/2013/04/quirk-implicit-conversion.html
Second suggestion:
var q4 = Quota.add(q1, q2, q3);
I recently came upon this article: http://www.2ality.com/2011/12/fake-operator-overloading.html .
It describes how you can redefine the valueOf method on objects to do something like operator overloading in javascript. It seems like you can only really perform mutator operations on the objects being operated on, so it wouldn't do what you want. Its interesting nonetheless tho.
I made a script that does operator overloading in JavaScript. It wasn't straight forward to make work, so there are a few quirks though. I will cross post the caveats here from the project page, otherwise you can find the link at the bottom:
Calculation results must be passed to a new object, so instead of (p1 + p2 + p3) you have to do new point(p1 + p2 + p3), (given your user defined object is named "point").
Only +, -, * and / are supported, the fifth arithmetic opperator % is not.
Coercion to strings (""+p1) and comparisons (p1 == p2) will not work as expected. New functions should be built for these purposes if needed, like (p1.val == p2.val).
Finally the computational resources needed to calculate the answer increases quadratically with the number of terms. Therefore only 6 terms is allowed in one calculation chain per default (although this can be increased). For longer calculation chains than that, split the calculations up, like: new point(new point(p1 + p2 + p3 + p4 + p5 + p6) + new point(p7 + p8 + p9 + p10 + p11 + p12))
The Github page.
In addition to what already have been said: overriding .valueOf() may help to produce quite powerful operator overloading. In proof-of-concept Fingers.js lib you can add event listeners in .NET style:
function hi() { console.log("hi") }
function stackoverflow() { console.log("stackoverflow") }
function bye() { console.log("bye") }
on(yourButton).click += hi + stackoverflow;
on(yourButton).click -= hi - bye;
Core idea is to replace temporarily valueOf when on() is called:
const extendedValueOf = function () {
if (handlers.length >= 16) {
throw new Error("Max 16 functions can be added/removed at once using on(..) syntax");
}
handlers.push(this); // save current function
return 1 << ((handlers.length - 1) * 2); // serialize it as a number.
};
Number returned can be then de-serialized back into function using handlers array. What's more it's possible extract bit values from final value (func1 + func2 - func3) so effectively you can understand what functions where added, and what functions were removed.
You can check out source on github and play with demo here.
Complete explanation exists in this article (it's for AS3, tough since it's ecmascript it will work for JS either).
I am not sure why people continue to answer this question with no!
There is absolutely a way which I will outline with a very very small script which your don't have to be John Resig to understand...
Before I do so I will also state that in JavaScript the way your constructor would have worked is by checking for arrays or iterating the 'arguments' literal.
e.g. In my constructor of my 'class' I would iterate the arugments, determine the type of the underlying arugments and process it intelligently.
This means that if you passed an array I would iterate the arugments to find an array and then iterate the array to do further processing depending on the type the element in the array.
E.g. -> new someClass([ instanceA, instanceB, instanceC])
However you guys are seeking a more "C" style approach to operator overloading which can actually be achived contrary to populare belief.
Here is a class which I have created using MooTools which does honor operator overloading. In plain old JavaScript you would just utilize the same toString method only attach it to the prototype of instance directly.
My main reason for displaying this approach is because of the text I continually read which states this functionality is "impossible" to emulate. Nothing is impossible only sufficently difficult and I will display this below...
//////
debugger;
//Make a counter to prove I am overloading operators
var counter = 0;
//A test class with a overriden operator
var TestClass = new Class({
Implements: [Options, Events],
stringValue: 'test',
intValue: 0,
initialize: function (options) {
if (options && options instanceof TestClass) {
//Copy or compose
this.intValue += options.intValue;
this.stringValue += options.stringValue;
} else {
this.intValue = counter++;
}
},
toString: function () {
debugger;
//Make a reference to myself
var self = this;
//Determine the logic which will handle overloads for like instances
if (self instanceof TestClass) return self.intValue;
//If this is not a like instance or we do not want to overload return the string value or a default.
return self.stringValue;
}
});
//Export the class
window.TestClass = TestClass;
//make an instance
var myTest = new TestClass();
//make another instance
var other = new TestClass();
//Make a value which is composed of the two utilizing the operator overload
var composed = myTest + other;
//Make a value which is composed of a string and a single value
var stringTest = '' + myTest;
//////
The most recent display of this nomenclature was observed at XDate's documentation page:
http://arshaw.com/xdate/
In this case I believe it was actually even easer, he could have used the prototype of the Date object to achive the same.
None the less the method I have given as an example which should portray this style of utilization for others.
Edit:
I have a complete implementation here:
http://netjs.codeplex.com/
Along with other goodies.
For some limited use cases you can have operator "overloading" effects:
function MyIntyClass() {
this.valueOf = function() { return Math.random(); }
}
var a = new MyIntyClass();
var b = new MyIntyClass();
a < b
false
a + b
0.6169137847609818
[a, b].sort() // O(n^2) ?
[myClass, myClass]
function MyStringyClass() {
this.valueOf = function() { return 'abcdefg'[Math.floor(Math.random()*7)]; }
}
c = new MyStringyClass();
'Hello, ' + c + '!'
Hello, f!
The above code is free to use under the MIT license. YMMV.
This is the best way I can think of phrasing this question, given this JavaScript "class" definition:
var Quota = function(hours, minutes, seconds){
if (arguments.length === 3) {
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
this.totalMilliseconds = Math.floor((hours * 3600000)) + Math.floor((minutes * 60000)) + Math.floor((seconds * 1000));
}
else if (arguments.length === 1) {
this.totalMilliseconds = hours;
this.hours = Math.floor(this.totalMilliseconds / 3600000);
this.minutes = Math.floor((this.totalMilliseconds % 3600000) / 60000);
this.seconds = Math.floor(((this.totalMilliseconds % 3600000) % 60000) / 1000);
}
this.padL = function(val){
return (val.toString().length === 1) ? "0" + val : val;
};
this.toString = function(){
return this.padL(this.hours) + ":" + this.padL(this.minutes) + ":" + this.padL(this.seconds);
};
this.valueOf = function(){
return this.totalMilliseconds;
};
};
and the following test setup code:
var q1 = new Quota(23, 58, 50);
var q2 = new Quota(0, 1, 0);
var q3 = new Quota(0, 0, 10);
console.log("Quota 01 is " + q1.toString()); // Prints "Quota 01 is 23:58:50"
console.log("Quota 02 is " + q2.toString()); // Prints "Quota 02 is 00:01:00"
console.log("Quota 03 is " + q3.toString()); // Prints "Quota 03 is 00:00:10"
Is there any way of implicitly creating q4 as a Quota object using the addition operator as follows...
var q4 = q1 + q2 + q3;
console.log("Quota 04 is " + q4.toString()); // Prints "Quota 04 is 86400000"
rather than resorting to...
var q4 = new Quota(q1 + q2 + q3);
console.log("Quota 04 is " + q4.toString()); // Prints "Quota 04 is 24:00:00"
If not what are the best practice recommendations in this area for making custom numeric JavaScript objects composable via the arithmetic operators?
As far as I'm aware, Javascript (at least as it exists now) doesn't support operator overloading.
The best I can suggest is a class method for making new quota objects from several others. Here's a quick example of what I mean:
// define an example "class"
var NumClass = function(value){
this.value = value;
}
NumClass.prototype.toInteger = function(){
return this.value;
}
// Add a static method that creates a new object from several others
NumClass.createFromObjects = function(){
var newValue = 0;
for (var i=0; i<arguments.length; i++){
newValue += arguments[i].toInteger();
}
return new this(newValue)
}
and use it like:
var n1 = new NumClass(1);
var n2 = new NumClass(2);
var n3 = new NumClass(3);
var combined = NumClass.createFromObjects(n1, n2, n3);
Unfortunately no.
For fallbacks, if you arranged the return values, you could use method chaining
var q4 = q1.plus(p2).plus(q3);
Since everyone down voted my other answer I wanted to post proof of concept code which does in fact work as intended.
This has been tested in chrome and IE.
//Operator Overloading
var myClass = function () {
//Privates
var intValue = Number(0),
stringValue = String('');
//Publics
this.valueOf = function () {
if (this instanceof myClass) return intValue;
return stringValue;
}
this.cast = function (type, call) {
if (!type) return;
if (!call) return type.bind(this);
return call.bind(new type(this)).call(this);
}
}
//Derived class
var anotherClass = function () {
//Store the base reference
this.constructor = myClass.apply(this);
var myString = 'Test',
myInt = 1;
this.valueOf = function () {
if (this instanceof myClass) return myInt;
return myString;
}
}
//Tests
var test = new myClass(),
anotherTest = new anotherClass(),
composed = test + anotherTest,
yaComposed = test.cast(Number, function () {
return this + anotherTest
}),
yaCComposed = anotherTest.cast(Number, function () {
return this + test;
}),
t = test.cast(anotherClass, function () {
return this + anotherTest
}),
tt = anotherTest.cast(myClass, function () {
return this + test;
});
debugger;
If someone would be so kind as to give a technical explanation WHY this is not good enough I would be happy to hear it out!
Paper.js does it, for example with point addition (docs):
var point = new Point(5, 10);
var result = point + 20;
console.log(result); // {x: 25, y: 30}
But it does it using its own custom script parser.
You can implicitly convert to integer or string, your objects.
Objects are only implicitly converted if JavaScript expects a number or a string. In the former case, the conversion takes three steps:
1.- Call valueOf(). If the result is primitive (not an object) then use it and convert it to a number.
2.- Otherwise, call toString(). If the result is primitive, use it and convert it to a number.
3.- Otherwise, throw a TypeError.
Example for step 1:
3 * { valueOf: function () { return 5 } }
If JavaScript converts to string, steps 1 and 2 are swapped: toString() is tried first, valueOf() second.
http://www.2ality.com/2013/04/quirk-implicit-conversion.html
Second suggestion:
var q4 = Quota.add(q1, q2, q3);
I recently came upon this article: http://www.2ality.com/2011/12/fake-operator-overloading.html .
It describes how you can redefine the valueOf method on objects to do something like operator overloading in javascript. It seems like you can only really perform mutator operations on the objects being operated on, so it wouldn't do what you want. Its interesting nonetheless tho.
I made a script that does operator overloading in JavaScript. It wasn't straight forward to make work, so there are a few quirks though. I will cross post the caveats here from the project page, otherwise you can find the link at the bottom:
Calculation results must be passed to a new object, so instead of (p1 + p2 + p3) you have to do new point(p1 + p2 + p3), (given your user defined object is named "point").
Only +, -, * and / are supported, the fifth arithmetic opperator % is not.
Coercion to strings (""+p1) and comparisons (p1 == p2) will not work as expected. New functions should be built for these purposes if needed, like (p1.val == p2.val).
Finally the computational resources needed to calculate the answer increases quadratically with the number of terms. Therefore only 6 terms is allowed in one calculation chain per default (although this can be increased). For longer calculation chains than that, split the calculations up, like: new point(new point(p1 + p2 + p3 + p4 + p5 + p6) + new point(p7 + p8 + p9 + p10 + p11 + p12))
The Github page.
In addition to what already have been said: overriding .valueOf() may help to produce quite powerful operator overloading. In proof-of-concept Fingers.js lib you can add event listeners in .NET style:
function hi() { console.log("hi") }
function stackoverflow() { console.log("stackoverflow") }
function bye() { console.log("bye") }
on(yourButton).click += hi + stackoverflow;
on(yourButton).click -= hi - bye;
Core idea is to replace temporarily valueOf when on() is called:
const extendedValueOf = function () {
if (handlers.length >= 16) {
throw new Error("Max 16 functions can be added/removed at once using on(..) syntax");
}
handlers.push(this); // save current function
return 1 << ((handlers.length - 1) * 2); // serialize it as a number.
};
Number returned can be then de-serialized back into function using handlers array. What's more it's possible extract bit values from final value (func1 + func2 - func3) so effectively you can understand what functions where added, and what functions were removed.
You can check out source on github and play with demo here.
Complete explanation exists in this article (it's for AS3, tough since it's ecmascript it will work for JS either).
I am not sure why people continue to answer this question with no!
There is absolutely a way which I will outline with a very very small script which your don't have to be John Resig to understand...
Before I do so I will also state that in JavaScript the way your constructor would have worked is by checking for arrays or iterating the 'arguments' literal.
e.g. In my constructor of my 'class' I would iterate the arugments, determine the type of the underlying arugments and process it intelligently.
This means that if you passed an array I would iterate the arugments to find an array and then iterate the array to do further processing depending on the type the element in the array.
E.g. -> new someClass([ instanceA, instanceB, instanceC])
However you guys are seeking a more "C" style approach to operator overloading which can actually be achived contrary to populare belief.
Here is a class which I have created using MooTools which does honor operator overloading. In plain old JavaScript you would just utilize the same toString method only attach it to the prototype of instance directly.
My main reason for displaying this approach is because of the text I continually read which states this functionality is "impossible" to emulate. Nothing is impossible only sufficently difficult and I will display this below...
//////
debugger;
//Make a counter to prove I am overloading operators
var counter = 0;
//A test class with a overriden operator
var TestClass = new Class({
Implements: [Options, Events],
stringValue: 'test',
intValue: 0,
initialize: function (options) {
if (options && options instanceof TestClass) {
//Copy or compose
this.intValue += options.intValue;
this.stringValue += options.stringValue;
} else {
this.intValue = counter++;
}
},
toString: function () {
debugger;
//Make a reference to myself
var self = this;
//Determine the logic which will handle overloads for like instances
if (self instanceof TestClass) return self.intValue;
//If this is not a like instance or we do not want to overload return the string value or a default.
return self.stringValue;
}
});
//Export the class
window.TestClass = TestClass;
//make an instance
var myTest = new TestClass();
//make another instance
var other = new TestClass();
//Make a value which is composed of the two utilizing the operator overload
var composed = myTest + other;
//Make a value which is composed of a string and a single value
var stringTest = '' + myTest;
//////
The most recent display of this nomenclature was observed at XDate's documentation page:
http://arshaw.com/xdate/
In this case I believe it was actually even easer, he could have used the prototype of the Date object to achive the same.
None the less the method I have given as an example which should portray this style of utilization for others.
Edit:
I have a complete implementation here:
http://netjs.codeplex.com/
Along with other goodies.
For some limited use cases you can have operator "overloading" effects:
function MyIntyClass() {
this.valueOf = function() { return Math.random(); }
}
var a = new MyIntyClass();
var b = new MyIntyClass();
a < b
false
a + b
0.6169137847609818
[a, b].sort() // O(n^2) ?
[myClass, myClass]
function MyStringyClass() {
this.valueOf = function() { return 'abcdefg'[Math.floor(Math.random()*7)]; }
}
c = new MyStringyClass();
'Hello, ' + c + '!'
Hello, f!
The above code is free to use under the MIT license. YMMV.
I'm writing a library for WebWorkers, and I want to test the difference between running a script in the main page thread, versus in one or more workers. The problem is: I can't find out of hand a short function which will strain my browser enough that I can observe the difference.
A quick search didn't return much, but it might just be that I don't really know what to search for; usually I try to optimise my code, not make it slower...
I'm looking for algorithms or patterns that can be easily implemented in pure Javascript, that do not depend on the DOM or XHR, and which can have an argument passed to limit or specify how far the calculation goes (no infinite algorithms); 1s < avg time < 10s.
Extra points if it can be built without recursion and if it does not incur a significant memory hog while still being as processor intensive as possible.
Try using the obvious (and bad) recursive implementation for the Fibonacci sequence:
function fib(x) {
if (x <= 0) return 0;
if (x == 1) return 1;
return fib(x-1) + fib(x-2);
}
Calling it with values of ~30 to ~35 (depending entirely on your system) should produce good "slow down" times in the range you seek. The call stack shouldn't get very deep and the algorithm is something like O(2^n).
/**
* Block CPU for the given amount of seconds
* #param {Number} [seconds]
*/
function slowdown(seconds = 0.5) {
const start = (new Date()).getTime()
while ((new Date()).getTime() - start < seconds * 1000){}
}
slowdown(2)
console.log('done')
Calling this method will slow code down for the given amount of seconds (with ~200ms precision).
Generate an array of numbers in reverse order and sort it.
var slowDown = function(n){
var arr = [];
for(var i = n; i >= 0; i--){
arr.push(i);
}
arr.sort(function(a,b){
return a - b;
});
return arr;
}
This can be called like so:
slowDown(100000);
Or whatever number you want to use.
Check out the benchmarking code referenced by the Google V8 Javascript Engine.
For some reason Bogosort comes to mind. Basically it's a sorting algorithm that consists of:
while not list.isInOrder():
list.randomize()
It has an average complexity of O(n * n!) with little memory, so it should slow things down pretty good.
The main downside is that its running time can be anywhere from O(n) to O(inf) (though really, O(inf) is pretty unlikely).
Everyone seems determined to be complicated. Why not this?
function waste_time(amount) {
for(var i = 0; i < amount; i++);
}
If you're concerned the browser will optimize the loop out of existence entirely, you can make it marginally more complicated:
function waste_time(amount) {
var tot = 0;
for(var i = 0; i < amount; i++)
tot += i;
}
Compute lots of square roots manually?
function sqrt(number, maxDecimal) {
var cDecimal = -1;
var cNumber = 0;
var direction = -1;
while(cNumber * cNumber !== number && cDecimal < maxDecimal) {
direction = -direction;
cDecimal++;
while((cNumber * cNumber - number) / Math.abs(cNumber * cNumber - number) === direction) cNumber += direction * Math.pow(10, -cDecimal);
}
return Math.abs(cNumber);
}
function performTest() {
for(var i = 0; i < 10000; i++) {
sqrt(i, 3);
}
}
Maybe this is what you are looking for:
var threadTest = function(durationMs, outputFkt, outputInterval) {
var startDateTime = (new Date()).getTime();
counter = 0,
testDateTime = null,
since = 0,
lastSince = -1;
do {
testDateTime = (new Date()).getTime();
counter++;
since = testDateTime - startDateTime;
if(typeof outputFkt != 'undefined' && lastSince != since && testDateTime % outputInterval == 0) {
outputFkt(counter, since);
lastSince = since;
}
} while(durationMs > since);
if(typeof outputFkt != 'undefined') {
outputFkt(counter, since);
}
return counter;
}
This method will simply repeat a check in a loop
durationMS - duartion it should run in miliseconds
OPTIONAL:
outputFkt - a callback method, for logging purpose function(currentCount, milisecondsSinceStart)
outputInterval - intervall the output function will be called
I figured since you do not want to test a real function, and even NP-Hard Problems have a ratio between input length and time this could be a easy way. You can measure performance at any interval and of course receive the number of loops as a return value, so you can easily measure how much threads interfere each others performance, with the callback even on a per cycle basis.
As an example here is how i called it (jQuery and Dom usage are here, but as you can see optional)
$(document).ready(function() {
var outputFkt = function(counter, since) {
$('body').append('<p>'+counter+', since '+since+'</p>');
};
threadTest(1000, outputFkt, 20);
});
A last Warning: Of course this function can not be more exact than JS itself. Since modern Browsers can do much more than one cycle in one Milisecond, there will be a little tail that gets cut.
Update
Thinking about it... actually using the ouputFkt callback for more than just output could give great insight. You could pass a method that uses some shared properties, or you could use it to test great memory usage.