Error with Deeply Equal To? - javascript

I am currently using FreeCodeCamp to try to learn basic JavaScript scripting. The problem that I am currently working on is:
http://www.freecodecamp.com/challenges/bonfire-map-the-debris.
The problem involves using OOP to solve a specific task (calculating orbital periods from the given altitude).
My code is as follows:
function orbitalPeriod(arr) {
var GM = 398600.4418;
var earthRadius = 6367.4447;
this.arr = arr;
for(var i = 0; i < arr.length; i++){
var altitude = this.arr[i]["avgAlt"] + earthRadius;
var calc = Math.round((2*Math.PI) * Math.sqrt(Math.pow(altitude,3) / GM),1);
this.arr[i]["avgAlt"] = calc;
}
return this.arr;
}
orbitalPeriod([{name : "sputkin", avgAlt : 35873.5553}]);
The issue is not with my calculations. Rather, when I submit my code, I get: "expected [ { name: 'sputkin', avgAlt: 86400 } ] to deeply equal [ Array (1) ]". Does anyone know why it is telling me that I should return an Array (1)?

The test suite is expecting the return array to contain an object with the properties name and orbitalPeriod - yours is returning an array containing an object with the properties name and avgAlt.
Side note, don't use the this keyword unless you're sure as to what it does - and I promise you it does not do what you think it does here.
Here's the solution, compare it with yours. Your calculations were correct, so good job on that part.
function orbitalPeriod(arr) {
var GM = 398600.4418,
earthRadius = 6367.4447,
output = [], altitude, calc;
for (var i = 0; i < arr.length; i++){
altitude = arr[i].avgAlt + earthRadius;
calc = Math.round((2*Math.PI) * Math.sqrt(Math.pow(altitude,3) / GM));
output.push({
name: arr[i].name,
orbitalPeriod: calc
});
}
return output;
}
orbitalPeriod([{name : "sputkin", avgAlt : 35873.5553}]);
Bonus note: Math.round() only takes one parameter.
Bonus answer:
Array.prototype.map() makes this super clean, if we're not tuning for performance.
function orbitalPeriod(arr) {
var GM = 398600.4418,
earthRadius = 6367.4447;
return arr.map(function (o) {
return {
name: o.name,
orbitalPeriod: Math.round((2 * Math.PI) * Math.sqrt(Math.pow(o.avgAlt + earthRadius, 3) / GM))
};
});
}
orbitalPeriod([{name : "sputkin", avgAlt : 35873.5553}]);

Related

Javascript adding multiple arrays in a loop

I am trying to add multiple arrays in javascript.
Here are my arrays I have made, and are working.
function getAmountSpent(){
var amountSpent = ((Math.random() * 500) + 1);
return amountSpent.toFixed(2)
}
function getGift(){
var gift = ((Math.random()* 50) + 1);
return gift.toFixed(2)
}
var names = ["Jeremy","Arun","Alisa","Rohan","Dana"];
var spent = [];
for (let i = 0; i < 5; i++) {
spent.push(getAmountSpent());
}
var gifts = [];
for (let i = 0; i<5; i++) {
gifts.push(getGift());
}
What I need help with is adding these arrays in a new function. I have began writing the code, and I am not sure what is wrong.
var totals =[];
for (let i=0; i<5; i++) {
totals.push(getSumTotals())
}
function getSumTotals(a){
totals= spent+(spent * gifts);
return totals.toFixed(2)
}
From what you can see, I am trying to add up the totals much like this:
totals[0] = spent[0] + (spent[0] * gifts[0]);
totals[1] = spent[1] + (spent[1] * gifts[1]);
totals[2] = spent[2] + (spent[2] * gifts[2]);
totals[3] = spent[3] + (spent[3] * gifts[3]);
totals[4] = spent[4] + (spent[4] * gifts[4]);
if it helps, the professor added guided instructions for function getSumTotals(a) stating:
This function will return the sum of the elements in array a.
You will be passing the array that holds your totals to
the parameter a. Be sure to treat the values in a as numbers.
I am not sure if this helps but here is the output to my document.
Current Total should equal (spent) + (spent * gifts). For instance, for Jeremy in this example, current total should equal:
$36.55 + ($36.55*0.0626) = $38.83. Since there are many variables involved, I am not 100% sure what I should write for function getSumTotals(a)
The parameter "a" is a placeholder because I am not sure how many parameter values I need, and the proper format I need to use.
As for the code...
You're both
not passing an index to getSumTotals
not using this parameter within getSumTotals to access your spent and gifts arrays
var totals =[];
for (let i=0; i<5; i++) {
totals.push(getSumTotals(i)) // you were missing i
}
function getSumTotals(idx) { // I took liberties to rename this
totals = spent[idx] + (spent[idx] * gifts[idx]);
return totals.toFixed(2);
}
Now for the Math...
All that said, this math of spent[i] + spent[i] * gifts[i] doesn't make much sense either. Was this specified in the problem?
you may use like this
defined gifts
gifts=[45,43,32];
defined spends
spends=[43,32,21];
this is the getSumTotal funtion
getSumTotal=(x)=>(x.a+x.b)
this is where added
totals=gifts.map((d1,i)=>{
return fu({a:gifts[i],b:spends[i]})
})
I understand this is your assignment, however - if the idea is to both generate arrays, and then add them together, it is a redundant step. Just use the name array to iterate once and do all your calculations within that single loop.
Here, I had some fun and took some liberties, but hopefully you see why multiple arrays are redundant.
function getSumTotals() {
const getAmountSpent = () => Math.random() * 500 + 1;
const getGift = () => Math.random() * 50 + 1;
const names = ["Jeremy", "Arun", "Alisa", "Rohan", "Dana"];
let totals = []
names.forEach((name, i) => {
let spent = getAmountSpent()
let gifts = getGift()
let $$$ = (spent + spent * gifts).toFixed(2);
totals[i] = $$$
console.log(`${name} cost me $${$$$}${'!'.repeat(($$$/1000) | 1)}`)
});
return totals;
}
getSumTotals()
Note, that toString returns a type of "String", but not "Number".
When you try to sum a number with string, you get a concatenated string "1" + 2 = "12"
To turn a string into Number, you must use a Number("str") function, or just a bunary + before the string:
console.log( "1" + 2 );
console.log( Number("1") + 2 );
console.log( +"1" + 2 );
Also, you use the same loop 3 times, but can use just one loop instead, and call all functions inside the one loop. And use your array.length instead of fixed number 5:
let names = ["Jeremy", "Arun", "Alisa", "Rohan", "Dana"];
let spent = [];
let gifts = [];
let totals = [];
for (let i = 0; i < names.length; i++) {
spent.push( getAmountSpent() );
gifts.push( getGift() );
totals.push( getSumTotals(i) );
}
console.log( totals );
function getAmountSpent() {
return rand(1, 500, 2);
}
function getGift() {
return rand(1, 50, 2);
}
function getSumTotals(i) {
return +( spent[i] * ( 1 + gifts[i] ) ).toFixed(2);
}
function rand(from, to, fixed = 0){
return +(Math.random()*( to - from ) + from).toFixed(fixed);
}
P.s. Math.random() returns a number between 0 (included) and 1 (not included). If you need a random number between (example) 20 and 100, Math.random()*(100-20) will give a number between 0 and 80. After adding +20 to the result, you get a number from 20 to 100. That's what does this formula Math.random()*( to - from ) + from
P.P.s. Another way, to get the same thing:
var names = ["Jeremy", "Arun", "Alisa", "Rohan", "Dana"].reduce( (prev, elem) => {
let spent = rand(1, 500, 2);
let gift = rand(1, 50, 2);
prev[elem] = new UserData( spent, gift );
return prev;
}, {});
console.log( "Jeremy spent: " + names.Jeremy.spent );
console.log( names );
function rand(from, to, fixed = 0){
return +(Math.random()*( to - from ) + from).toFixed(fixed);
}
function UserData(spent, gift){
this.spent = spent;
this.gift = gift;
this.total = +(spent * ( 1 + gift )).toFixed(2);
}
/* Google → Array reduce, Constructor functions */
function getAmountSpent(){
let amountSpent = ((Math.random() * 500) + 1);
return Number(amountSpent.toFixed(2))
}
function getGift(){
let gift = ((Math.random()* 50) + 1);
return Number(gift.toFixed(2))
}
let names = ["Jeremy","Arun","Alisa","Rohan","Dana"];
let spent = [];
let gifts = [];
let totals =[];
for (let i = 0; i < names.length; i++) {
spent.push(getAmountSpent());
gifts.push(getGift());
totals[i] = (spent[i]+(spent[i] * gifts[i])).toFixed(2);
totals[i] = parseFloat(totals[i])
}
Hi there
I don't think you need a function to add the totals. you just need to loop through and assign totals[i] to spent[i] + (spent[i] * gifts[i]).
then you can use the parseFloat and toFixed function to change the string to a number. remember toFixed() function turns numbers to string. so you need to use the parseFloat to change it to number again as shown in the code above. or you can come up with an easy way of changing it to number. I hope this helps!

JavaScript: function return closest value

I am trying to return the value of the closest object to my position in a function.
I tried to put the entities in a array and than I tried return closest object to my position with a for loop, but it did not work. How can I do this?
function getMyEntity() {
return Game.currentGame.world.localPlayer.entity.getFromTick();
}
function getOtherEntity() {
var MyPlayerEntity = getMyEntity();
var entities = Game.currentGame.world.entities;
for (var uid in entities) {
// how i get closest entity to my player entity here?
var gameObject = entities[uid].fromTick;
console.log(entities[uid].fromTick.position, MyPlayerEntity.position)
if (gameObject.entityClass == "Prop" && gameObject.uid !== MyPlayerEntity.uid) {
return gameObject;
}
}
}
function aimAssist() {
var MyPlayerEntity = getMyEntity();
var OtherEntity = getOtherEntity();
if (OtherEntity == undefined) return
var aimPosition = {
x: OtherEntity.position.x - MyPlayerEntity.position.x,
y: OtherEntity.position.y - MyPlayerEntity.position.y
}
return aimPosition;
}
I'll give you a bad advice, for now it'll work, as your game grows it will be bad because of O(n^2) complexity. Read a bit about quadtrees and see if you can do that. Meanwhile you can compare the euclidean distance, do not need to take the square root:
Object.keys(entities)
.map(function(d,i){
var dx = entities[d].fromTick.position.x - MyPlayerEntity.position.x,
dy = entities[d].fromTick.position.y - MyPlayerEntity.position.y,
result = {D:(dx * dx) + (dy + dy), obj:entities[d] , valueOf: function(){return this.D};
return result;
}).sort(function(a,b){
return a-b;
})[0].obj; //this returns the closest one
So your original function becomes this:
function getOtherEntity() {
var MyPlayerEntity = getMyEntity();
var entities = Game.currentGame.world.entities;
return Object.keys(entities)
.map(function(d,i){
var dx = entities[d].fromTick.position.x - MyPlayerEntity.position.x,
dy = entities[d].fromTick.position.y - MyPlayerEntity.position.y,
result = {D:(dx * dx) + (dy + dy), obj:entities[d] , valueOf: function(){return this.D};
return result;
}).sort(function(a,b){
return a-b;
})[0].obj; //this returns the closest one
}
I'd create an array of objects which contain the Object-ID and distance, and sort it by distance.
The first array-item is the closest to the player.
The array may look like
[{uid: 1234, distance: 12}, {uid: 1235, distance: 16}, ...]
You can sort arrays with arrayName.sort(sortingFunction)
assuming you can get x and y coordinates from gameObject.position and MyPlayerEntity.position you could use a bit of Pitagoras: c^2 = a^2 +b^2, with c being the distance
let a = gameObject.position.x - MyPlayerEntity.position.x;
let b = gameObject.position.y - MyPlayerEntity.position.y;
let distanceSquared = a*a + b*b;
Since you don't seem to need the exact distance and sqrt() is expensive, you can use the value in distanceSquared and other variables declared outside of the loop to keep track
let closestDistance;
let closest;
to make the proper comparisons
if(distanceSquared < closestDistance){
closestDistance = distanceSquared;
closest = gameObject;
}
After you loop through the array, the closest entity reference should be:
return closest;

Can't get Lotka-Volterra equations to oscillate stable with math.js

I'm trying to implement a simple Lotka-Volterra system in JavaScript, but get different result from what I see in academic papers and slides. This is my equations:
sim2.eval("dxdt(x, y) = (2 * x) - (x * y)");
sim2.eval("dydt(x, y) = (-0.25 * y) + (x * y)");
using coefficients a = 2, b = 1, c = 0.25 and d = 1. Yet, my result looks like this:
when I expected a stable oscillation as seen in these PDF slides:
Could it be the implementation of ndsolve that causes this? Or a machine error in JavaScript due to floating-point arithmetic?
Disregard, the error was simply using a too big evaluation step (dt = 0.1, must be 0.01 at least). The numerical method used is known for this problem.
For serious purposes use a higher order method, the minimum is fixed step classical Runge-Kutta. Then you can also use dt=0.1, it is stable for multiple periods, I tried tfinal=300 without problems. However you will see the step size in the graph as it is visibly piecewise linear. This is much reduced with half the step size, dt=0.05.
function odesolveRK4(f, x0, dt, tmax) {
var n = f.size()[0]; // Number of variables
var x = x0.clone(),xh=[]; // Current values of variables
var dxdt = [], k1=[], k2=[], k3=[], k4=[]; // Temporary variable to hold time-derivatives
var result = []; // Contains entire solution
var nsteps = math.divide(tmax, dt); // Number of time steps
dt2 = math.divide(dt,2);
dt6 = math.divide(dt,6);
for(var i=0; i<nsteps; i++) {
// compute the 4 stages if the classical order-4 Runge-Kutta method
k1 = f.map(function(fj) {return fj.apply(null, x.toArray()); } );
xh = math.add(x, math.multiply(k1, dt2));
k2 = f.map(function(fj) {return fj.apply(null, xh.toArray()); } );
xh = math.add(x, math.multiply(k2, dt2));
k3 = f.map(function(fj) {return fj.apply(null, xh.toArray()); } );
xh = math.add(x, math.multiply(k3, dt));
k4 = f.map(function(fj) {return fj.apply(null, xh.toArray()); } );
x = math.add(x, math.multiply(math.add(math.add(k1,k4), math.multiply(math.add(k2,k3),2)), dt6))
if( 0==i%50) console.log("%3d %o %o",i,dt,x.toString());
result.push(x.clone());
}
return math.matrix(result);
}
math.import({odesolveRK4:odesolveRK4});

Javascript prototype operator performance: saves memory, but is it faster?

I read here (Douglas Crockford) using prototype operator to add methods to Javascript classes saves also memory.
Then I read in this John Resig's article "Instantiating a function with a bunch of prototype properties is very, very, fast", but is he talking about using prototype in the standard way, or is he talking about his specific example in his article?
For example, is creating this object:
function Class1()
{
this.showMsg = function(string) { alert(string); }
}
var c = new Class1();
c.showMsg();
slower than creating this object, then?
function Class1() {}
Class1.prototype.showMsg = function(string) { alert(string); }
var c = new Class1();
c.showMsg();
P.S.
I know prototype is used to create inheritance and singleton object etc. But this question does not have anyhting to do with these subjects.
EDIT: to whom it might be interested also in performance comparison between a JS object and a JS static objet can read this answer below. Static object are definitely faster, obviously they can be usued only when you don't need more than one instance of the object.
Edit in 2021:
This question was asked in 2010 when class was not available in JS. Nowadays, class has been so optimized that there is no excuse not to use it. If you need to use new, use class. But back in 2010 you had two options when binding methods to their object constructors -- one was to bind functions inside the function constructor using this and the other was to bind them outside the constructor using prototype. #MarcoDemaio's question has very concise examples. When class was added to JS, early implementations were close in performance, but usually slower. That's not remotely true anymore. Just use class. I can think of no reason to use prototype today.
It was an interesting question, so I ran some very simple tests (I should have restarted my browsers to clear out the memory, but I didn't; take this for what it's worth). It looks like at least on Safari and Firefox, prototype runs significantly faster [edit: not 20x as stated earlier]. I'm sure a real-world test with fully-featured objects would be a better comparison. The code I ran was this (I ran the tests several times, separately):
var X,Y, x,y, i, intNow;
X = function() {};
X.prototype.message = function(s) { var mymessage = s + "";}
X.prototype.addition = function(i,j) { return (i *2 + j * 2) / 2; }
Y = function() {
this.message = function(s) { var mymessage = s + "";}
this.addition = function(i,j) { return (i *2 + j * 2) / 2; }
};
intNow = (new Date()).getTime();
for (i = 0; i < 10000000; i++) {
y = new Y();
y.message('hi');
y.addition(i,2)
}
console.log((new Date()).getTime() - intNow); //FF=5206ms; Safari=1554
intNow = (new Date()).getTime();
for (i = 0; i < 10000000; i++) {
x = new X();
x.message('hi');
x.addition(i,2)
}
console.log((new Date()).getTime() - intNow);//FF=3894ms;Safari=606
It's a real shame, because I really hate using prototype. I like my object code to be self-encapsulated, and not allowed to drift. I guess when speed matters, though, I don't have a choice. Darn.
[Edit] Many thanks to #Kevin who pointed out my previous code was wrong, giving a huge boost to the reported speed of the prototype method. After fixing, prototype is still around significantly faster, but the difference is not as enormous.
I would guess that it depends on the type of object you want to create. I ran a similar test as Andrew, but with a static object, and the static object won hands down. Here's the test:
var X, Y, Z, x, y, z;
X = function() {};
X.prototype.message = function(s) {
var mymessage = s + "";
}
X.prototype.addition = function(i, j) {
return (i * 2 + j * 2) / 2;
}
Y = function() {
this.message = function(s) {
var mymessage = s + "";
}
this.addition = function(i, j) {
return (i * 2 + j * 2) / 2;
}
};
Z = {
message: function(s) {
var mymessage = s + "";
},
addition: function(i, j) {
return (i * 2 + j * 2) / 2;
}
}
function TestPerformance() {
var closureStartDateTime = new Date();
for (var i = 0; i < 100000; i++) {
y = new Y();
y.message('hi');
y.addition(i, 2);
}
var closureEndDateTime = new Date();
var prototypeStartDateTime = new Date();
for (var i = 0; i < 100000; i++) {
x = new X();
x.message('hi');
x.addition(i, 2);
}
var prototypeEndDateTime = new Date();
var staticObjectStartDateTime = new Date();
for (var i = 0; i < 100000; i++) {
z = Z; // obviously you don't really need this
z.message('hi');
z.addition(i, 2);
}
var staticObjectEndDateTime = new Date();
var closureTime = closureEndDateTime.getTime() - closureStartDateTime.getTime();
var prototypeTime = prototypeEndDateTime.getTime() - prototypeStartDateTime.getTime();
var staticTime = staticObjectEndDateTime.getTime() - staticObjectStartDateTime.getTime();
console.log("Closure time: " + closureTime + ", prototype time: " + prototypeTime + ", static object time: " + staticTime);
}
TestPerformance();
This test is a modification of code I found at:
Link
Results:
IE6: closure time: 1062, prototype time: 766, static object time: 406
IE8: closure time: 781, prototype time: 406, static object time: 188
FF: closure time: 233, prototype time: 141, static object time: 94
Safari: closure time: 152, prototype time: 12, static object time: 6
Chrome: closure time: 13, prototype time: 8, static object time: 3
The lesson learned is that if you DON'T have a need to instantiate many different objects from the same class, then creating it as a static object wins hands down. So think carefully about what kind of class you really need.
So I decided to test this as well. I tested creation time, execution time, and memory use. I used Nodejs v0.8.12 and the mocha test framework running on a Mac Book Pro booted into Windows 7. The 'fast' results are using prototypes and the 'slow' ones are using module pattern. I created 1 million of each type of object and then accessed the 4 methods in each object. Here are the results:
c:\ABoxAbove>mocha test/test_andrew.js
Fast Allocation took:170 msec
·Fast Access took:826 msec
state[0] = First0
Free Memory:5006495744
·Slow Allocation took:999 msec
·Slow Access took:599 msec
state[0] = First0
Free Memory:4639649792
Mem diff:358248k
Mem overhead per obj:366.845952bytes
? 4 tests complete (2.6 seconds)
The code is as follows:
var assert = require("assert"), os = require('os');
function Fast (){}
Fast.prototype = {
state:"",
getState:function (){return this.state;},
setState:function (_state){this.state = _state;},
name:"",
getName:function (){return this.name;},
setName:function (_name){this.name = _name;}
};
function Slow (){
var state, name;
return{
getState:function (){return this.state;},
setState:function (_state){this.state = _state;},
getName:function (){return this.name;},
setName:function (_name){this.name = _name;}
};
}
describe('test supposed fast prototype', function(){
var count = 1000000, i, objs = [count], state = "First", name="Test";
var ts, diff, mem;
it ('should allocate a bunch of objects quickly', function (done){
ts = Date.now ();
for (i = 0; i < count; ++i){objs[i] = new Fast ();}
diff = Date.now () - ts;
console.log ("Fast Allocation took:%d msec", diff);
done ();
});
it ('should access a bunch of objects quickly', function (done){
ts = Date.now ();
for (i = 0; i < count; ++i){
objs[i].setState (state + i);
assert (objs[i].getState () === state + i, "States should be equal");
objs[i].setName (name + i);
assert (objs[i].getName () === name + i, "Names should be equal");
}
diff = Date.now() - ts;
console.log ("Fast Access took:%d msec", diff);
console.log ("state[0] = " + objs[0].getState ());
mem = os.freemem();
console.log ("Free Memory:" + mem + "\n");
done ();
});
it ('should allocate a bunch of objects slowly', function (done){
ts = Date.now ();
for (i = 0; i < count; ++i){objs[i] = Slow ();}
diff = Date.now() - ts;
console.log ("Slow Allocation took:%d msec", diff);
done ();
});
it ('should access a bunch of objects slowly', function (done){
ts = Date.now ();
for (i = 0; i < count; ++i){
objs[i].setState (state + i);
assert (objs[i].getState () === state + i, "States should be equal");
objs[i].setName (name + i);
assert (objs[i].getName () === name + i, "Names should be equal");
}
diff = Date.now() - ts;
console.log ("Slow Access took:%d msec", diff);
console.log ("state[0] = " + objs[0].getState ());
var mem2 = os.freemem();
console.log ("Free Memory:" + mem2 + "\n");
console.log ("Mem diff:" + (mem - mem2) / 1024 + "k");
console.log ("Mem overhead per obj:" + (mem - mem2) / count + 'bytes');
done ();
});
});
Conclusion: This backs up what others in this post have found. If you are constantly creating objects then the prototype mechanism is clearly faster. If your code spends most of its time accessing objects then the module pattern is faster. If you are sensitive about memory use, the prototype mechanism uses ~360 bytes less per object.
Intuitively, it seems that it would be more memory-efficient and faster to create functions on the prototype: the function's only created once, not each time a new instance is created.
However, there will be a slight performance difference when it's time to access the function. When c.showMsg is referenced, the JavaScript runtime first checks for the property on c. If it's not found, c's prototype is then checked.
So, creating the property on the instance would result in slightly faster access time - but this might only be an issue for a very deep prototype hierarchy.
We need to separate object construction and usage.
When declaring a function on a prototype, it is shared between all instances. When declaring a function in a constructor, this is recreated every time new instance is made. Given that, we need to benchmark construction and usage separately to have better results. That is what I did and want to share the results with you. This benchmark does not test for speed of construction.
function ThisFunc() {
this.value = 0;
this.increment = function(){
this.value++;
}
}
function ProtFunc() {
this.value = 0;
}
ProtFunc.prototype.increment = function (){
this.value++;
}
function ClosFunc() {
var value = 0;
return {
increment:function(){
value++;
}
};
}
var thisInstance = new ThisFunc;
var iterations = 1000000;
var intNow = (new Date()).getTime();
for (i = 0; i < iterations; i++) {
thisInstance.increment();
}
console.log(`ThisFunc: ${(new Date()).getTime() - intNow}`); // 27ms node v4.6.0
var protInstance = new ProtFunc;
intNow = (new Date()).getTime();
for (i = 0; i < iterations; i++) {
protInstance.increment();
}
console.log(`ProtFunc: ${(new Date()).getTime() - intNow}`); // 4ms node v4.6.0
var closInstance = ClosFunc();
intNow = (new Date()).getTime();
for (i = 0; i < iterations; i++) {
closInstance.increment();
}
console.log(`ClosFunc: ${(new Date()).getTime() - intNow}`); // 7ms node v4.6.0
From these results we can see that the prototype version is the fastest (4ms), but the closure version is very close (7ms). You may still need to benchmark for your particular case.
So:
We can use prototype version when we need to have every bit of performance or share functions between instances.
We can use other versions when what we want is the features they provide. (private state encapsulation, readability etc.)
PS: I used Andrew's answer as a reference. Used the same loops and notation.
I ran my own tests.
The first conclusion is, that static access is actually slower than real prototyping. Interestingly, the Version 23 of this test has a flawed prototyping (Variable X) in it, which just returns the completely overridden prototype object over and over again and when I was creating my test, this prototyping was still slower than my "real prototype" test.
Anyway, to the answer: Unless my test is flawed, it shows that real prototyping is fastest. It beats or is at least equal to the static object when ignoring instantiation. this-assignments on instantiation and private variables are both much slower. I wouldn't have guessed private variables would be this slow.
It might be of interest that I extended the prototype Object with jQuery.extend in between and it was about the same speed as the direct assignment. The extend was outside the test itself, of course. At least this is a way to circumvent writing annoying ".prototype."-Parts all the time.
High Resolution Browser Performance API Tests
None of the tests here are taking advantage of the performance API for high resolution testing so I wrote one that will show current fastest results for many different scenarios including 2 that are faster than any of the other answers on most runs.
Fasted in each category (10,000 iterations)
Property access only (~0.5ms): { __proto__: Type }
Looping object creation with property access (<3ms): Object.create(Type)
The code uses ES6 without babel transpilation to ensure accuracy. It works in current chrome. Run the test below to see the breakdown.
function profile () {
function test ( name
, define
, construct
, { index = 0
, count = 10000
, ordinals = [ 0, 1 ]
, constructPrior = false
} = {}
) {
performance.clearMarks()
performance.clearMeasures()
const symbols = { type: Symbol('type') }
const marks = (
{ __proto__: null
, start: `${name}_start`
, define: `${name}_define`
, construct: `${name}_construct`
, end: `${name}_end`
}
)
performance.mark(marks.start)
let Type = define()
performance.mark(marks.define)
let obj = constructPrior ? construct(Type) : null
do {
if(!constructPrior)
obj = construct(Type)
if(index === 0)
performance.mark(marks.construct)
const measureOrdinal = ordinals.includes(index)
if(measureOrdinal)
performance.mark(`${name}_ordinal_${index}_pre`)
obj.message('hi')
obj.addition(index, 2)
if(measureOrdinal)
performance.mark(`${name}_ordinal_${index}_post`)
} while (++index < count)
performance.mark(marks.end)
const measureMarks = Object.assign (
{ [`${name}_define`]: [ marks.start, marks.define ]
, [`${name}_construct`]: [ marks.define, marks.construct ]
, [`${name}_loop`]: [ marks.construct, marks.end ]
, [`${name}_total`]: [ marks.start, marks.end ]
}
, ordinals.reduce((reduction, i) => Object.assign(reduction, { [`${name}_ordinal_${i}`]: [ `${name}_ordinal_${i}_pre`, `${name}_ordinal_${i}_post` ] }), {})
)
Object.keys(measureMarks).forEach((key) => performance.measure(key, ...measureMarks[key]))
const measures = performance.getEntriesByType('measure').map(x => Object.assign(x, { endTime: x.startTime + x.duration }))
measures.sort((a, b) => a.endTime - b.endTime)
const durations = measures.reduce((reduction, measure) => Object.assign(reduction, { [measure.name]: measure.duration }), {})
return (
{ [symbols.type]: 'profile'
, profile: name
, duration: durations[`${name}_total`]
, durations
, measures
}
)
}
const refs = (
{ __proto__: null
, message: function(s) { var mymessage = s + '' }
, addition: function(i, j) { return (i *2 + j * 2) / 2 }
}
)
const testArgs = [
[ 'constructor'
, function define() {
return function Type () {
this.message = refs.message
this.addition = refs.addition
}
}
, function construct(Type) {
return new Type()
}
]
, [ 'prototype'
, function define() {
function Type () {
}
Type.prototype.message = refs.message
Type.prototype.addition = refs.addition
return Type
}
, function construct(Type) {
return new Type()
}
]
, [ 'Object.create'
, function define() {
return (
{ __proto__: null
, message: refs.message
, addition: refs.addition
}
)
}
, function construct(Type) {
return Object.create(Type)
}
]
, [ 'proto'
, function define() {
return (
{ __proto__: null
, message: refs.message
, addition: refs.addition
}
)
}
, function construct(Type) {
return { __proto__: Type }
}
]
]
return testArgs.reduce(
(reduction, [ name, ...args ]) => (
Object.assign( reduction
, { [name]: (
{ normal: test(name, ...args, { constructPrior: true })
, reconstruct: test(`${name}_reconstruct`, ...args, { constructPrior: false })
}
)
}
)
)
, {})
}
let profiled = profile()
const breakdown = Object.keys(profiled).reduce((reduction, name) => [ ...reduction, ...Object.keys(profiled[name]).reduce((r, type) => [ ...r, { profile: `${name}_${type}`, duration: profiled[name][type].duration } ], []) ], [])
breakdown.sort((a, b) => a.duration - b.duration)
try {
const Pre = props => React.createElement('pre', { children: JSON.stringify(props.children, null, 2) })
ReactDOM.render(React.createElement(Pre, { children: { breakdown, profiled } }), document.getElementById('profile'))
} catch(err) {
console.error(err)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="profile"></div>
I'm sure that as far as instantiating the object goes, it's way faster and also consumes less memory, no doubts about that, but I would think that the javascript engine needs to loop through all the properties of the object to determine if the property/method invoked is part of that object and if not, then go check for the prototype. I am not 100% sure about this but I'm assuming that's how it works and if so, then in SOME cases where your object has a LOT of methods added to it, instantiated only once and used heavily, then it could possibly be a little slower, but that's just a supposition I haven't tested anything.
But in the end, I would still agree that as a general rules, using prototype will be faster.
Funny thing though. It depends not that much on which type of object you create and it matters how you write an example. Likewise i ran similar test as shmuel613 who wrote a similair test as Andrew. The first test is creating a single instance of a constructor, a class and an object literal and then measures the speed of execution from the constructor's instance functions, class's prototype methods and object literal's static functions:
var Y, Z, x, y, z;
class X {
message(s) {
var mymessage = s + "";
};
addition(i, j) {
return (i * 2 + j * 2) / 2;
};
};
Y = function () {
this.message = function (s) {
var mymessage = s + "";
};
this.addition = function (i, j) {
return (i * 2 + j * 2) / 2;
};
};
Z = {
message(s) {
var mymessage = s + "";
},
addition(i, j) {
return (i * 2 + j * 2) / 2;
}
}
function TestPerformance() {
console.time("Closure time:");
y = new Y(); // create a single instance
for (var i = 0; i < 100000; i++) {
// I am comparing a single instance with the other single instances
y.message('hi');
y.addition(i, 2);
}
console.timeEnd("Closure time:");
console.time("Prototype time:");
x = new X(); // create a single instance
for (var i = 0; i < 100000; i++) {
// I am comparing a single instance with the other single instances
x.message('hi');
x.addition(i, 2);
}
console.timeEnd("Prototype time:");
console.time("Static object time:");
for (var i = 0; i < 100000; i++) {
z = Z; // obviously you don't really need this
z.message('hi');
z.addition(i, 2);
}
console.timeEnd("Static object time:");
}
TestPerformance();
The second test measures the speed of execution of creating many instances of a constructor, a class and object literals followed by executing the instance functions, prototype methods and static methods:
var Y, x, y, z;
class X {
message(s) {
var mymessage = s + "";
};
addition(i, j) {
return (i * 2 + j * 2) / 2;
};
};
Y = function () {
this.message = function (s) {
var mymessage = s + "";
};
this.addition = function (i, j) {
return (i * 2 + j * 2) / 2;
};
};
function TestPerformance() {
console.time("Closure time:");
//y = new Y()
for (var i = 0; i < 100000; i++) {
y = new Y(); // creating an instance
y.message('hi');
y.addition(i, 2);
}
console.timeEnd("Closure time:");
console.time("Prototype time:");
//x = new X();
for (var i = 0; i < 100000; i++) {
x = new X(); // creating an instance
x.message('hi');
x.addition(i, 2);
}
console.timeEnd("Prototype time:");
console.time("Static object time:");
for (var i = 0; i < 100000; i++) {
z = {
message(s) {
var mymessage = s + "";
},
addition(i, j) {
return (i * 2 + j * 2) / 2;
}
}; // creating an instance such as from factory functions
z.message('hi');
z.addition(i, 2);
}
console.timeEnd("Static object time:");
}
TestPerformance();
The lesson learned is that DON'T blindly evolve a prejudice against something without being thorough. The execution speed from instance functions of a constructor (pre ES2016 classes) and the speed from prototype methods of a class are really just as fast as the execution speed from static functions of a object. However the creation speed followed by execution speed of a constructor instance with instance functions versus the creation speed of a class instance with prototype methods versus the creation speed of object literals with static methods shows rather that classes with prototype methods are faster created and executed on Chrome, Microsoft edge, and Opera. The creation speed of an object literal with static methods is only faster at Mozilla firefox
So, creating the property on the instance would result in slightly faster access time - but this might only be an issue for a very deep prototype hierarchy.
Actually the result is different then we could expect - access time to prototyped methods is faster then accessing to the methods attached exactly to the object (FF tested).

Pick random property from a Javascript object

Suppose you have a Javascript object like:
{cat: 'meow', dog: 'woof', snake: 'hiss'}
Is there a more concise way to pick a random property from the object than this long winded way I came up with:
function pickRandomProperty(obj) {
var prop, len = 0, randomPos, pos = 0;
for (prop in obj) {
if (obj.hasOwnProperty(prop)) {
len += 1;
}
}
randomPos = Math.floor(Math.random() * len);
for (prop in obj) {
if (obj.hasOwnProperty(prop)) {
if (pos === randomPos) {
return prop;
}
pos += 1;
}
}
}
The chosen answer will work well. However, this answer will run faster:
var randomProperty = function (obj) {
var keys = Object.keys(obj);
return obj[keys[ keys.length * Math.random() << 0]];
};
Picking a random element from a stream
function pickRandomProperty(obj) {
var result;
var count = 0;
for (var prop in obj)
if (Math.random() < 1/++count)
result = prop;
return result;
}
I didn't think any of the examples were confusing enough, so here's a really hard to read example doing the same thing.
Edit: You probably shouldn't do this unless you want your coworkers to hate you.
var animals = {
'cat': 'meow',
'dog': 'woof',
'cow': 'moo',
'sheep': 'baaah',
'bird': 'tweet'
};
// Random Key
console.log(Object.keys(animals)[Math.floor(Math.random()*Object.keys(animals).length)]);
// Random Value
console.log(animals[Object.keys(animals)[Math.floor(Math.random()*Object.keys(animals).length)]]);
Explanation:
// gets an array of keys in the animals object.
Object.keys(animals)
// This is a number between 0 and the length of the number of keys in the animals object
Math.floor(Math.random()*Object.keys(animals).length)
// Thus this will return a random key
// Object.keys(animals)[0], Object.keys(animals)[1], etc
Object.keys(animals)[Math.floor(Math.random()*Object.keys(animals).length)]
// Then of course you can use the random key to get a random value
// animals['cat'], animals['dog'], animals['cow'], etc
animals[Object.keys(animals)[Math.floor(Math.random()*Object.keys(animals).length)]]
Long hand, less confusing:
var animalArray = Object.keys(animals);
var randomNumber = Math.random();
var animalIndex = Math.floor(randomNumber * animalArray.length);
var randomKey = animalArray[animalIndex];
// This will course this will return the value of the randomKey
// instead of a fresh random value
var randomValue = animals[randomKey];
If you are capable of using libraries, you may find that Lo-Dash JS library has lots of very useful methods for such cases. In this case, go ahead and check _.sample().
(Note Lo-Dash convention is naming the library object _.
Don't forget to check installation in the same page to set it up for your project.)
_.sample([1, 2, 3, 4]);
// → 2
In your case, go ahead and use:
_.sample({
cat: 'meow',
dog: 'woof',
mouse: 'squeak'
});
// → "woof"
You can just build an array of keys while walking through the object.
var keys = [];
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
keys.push(prop);
}
}
Then, randomly pick an element from the keys:
return keys[keys.length * Math.random() << 0];
If you're using underscore.js you can do:
_.sample(Object.keys(animals));
Extra:
If you need multiple random properties add a number:
_.sample(Object.keys(animals), 3);
If you need a new object with only those random properties:
const props = _.sample(Object.keys(animals), 3);
const newObject = _.pick(animals, (val, key) => props.indexOf(key) > -1);
You can use the following code to pick a random property from a JavaScript object:
function randomobj(obj) {
var objkeys = Object.keys(obj)
return objkeys[Math.floor(Math.random() * objkeys.length)]
}
var example = {foo:"bar",hi:"hello"}
var randomval = example[randomobj(example)] // will return to value
// do something
Another simple way to do this would be defining a function that applies Math.random() function.
This function returns a random integer that ranges from the 'min'
function getRandomArbitrary(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
Then, extract either a 'key' or a 'value' or 'both' from your Javascript object each time you supply the above function as a parameter.
var randNum = getRandomArbitrary(0, 7);
var index = randNum;
return Object.key(index); // Returns a random key
return Object.values(index); //Returns the corresponding value.
A lot of great answers here, so let me just try to spread the awareness of the bitwise NOT (~) operator in its double-trouble variant (which I'm pretty sure I learned about on StackOverflow, anways).
Typically, you'd pick a random number from one to ten like this:
Math.floor(Math.random()*10) + 1
But bitwise operation means rounding gets done faster, so the following implementation has the potential to be noticeably more performant, assuming you're doing enough truckloads of these operations:
~~(Math.random()*10) + 1

Categories

Resources