Can I refactor this code in any way in javascript? [closed] - javascript

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 7 years ago.
Improve this question
I have a 'render' function:
render: function(playerId){
this.getTotalPoints(playerId);
// and some other code after this;
}
This 'render' function may be executed with or without a playerId. This is the getTotalPoints function:
getTotalPoints: function(playerId){
if(playerId){
this.allplayers[playerId].totalPoints = this.calculatePoints(this.allplayers[playerId].cards);
}else{
this.allplayers.forEach(function(element, index){
element.totalPoints = this.calculatePoints(element.cards);
}.bind(this));
}
}
And the third function that actually calculates the points
calculatePoints: function(cards){
points = 0;
for( var i = 0; i < cards.length; i++){
points+=cards[i].points;
};
return points;
}
I am repeating myself in getTotalPoints, where I have a call to this.calculatePoints - one for a single player and then one for all the players, depending on whether the playerId is set or not.
Is there any chance I can avoid this and simplify the code?

I would do something like:
getTotalPoints: function(playerId){
var selected = playerId ? [this.allplayers[playerId]] : this.allplayers;
selected.forEach(function(element, index){
element.totalPoints = this.calculatePoints(element.cards);
}.bind(this));
}
However, since you're changing the state of the players, I would not call the function getTotalPoints, maybe computeTotalPoints?

I see two different functions: calculatePointsForPlayer and calculatePointsForPlayers. Second function will call first function.

Related

How to make this function call add(4)(5)(6) work? which will return 15 [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I know one way is there any other way to make this type of function call and get the correct addition.
My answer:
function add(x) {
return function(y) {
return function(z) {
return x + y + z
}
}
}
add(4)(5)(6)
It means that the first function returns another function and then that returned function is called immediately then that function returns another function which is then called immediately which will give us the final answer.
As others have mentioned, you can't quite do that. You could create a fluent interface sort of similar to that though, by extending the Number prototype:
Number.prototype.add = function(num) {
return this.valueOf() + num;
}
Then, you could use it like this:
// Instead of add(2)(7)(11):
(0).add(2)
.add(7)
.add(11);
// Or:
(2).add(7).add(11);
Not sure I'd recommend actually doing that, but it's a fun exercise.
You should pass an array to your function as parameter and make a loop on it:
function add(num) {
var sum = 0;
for (var i = 0; i < num.length; i++) {
sum += num[i];
}
return sum;
}
alert(add([10,20,30]));//will return 60
You can't do that. The first set of parenthesis is there to pass the parameter to your function. You are allowed to pass more than one parameter to your function like this:
var total = add(2, 8);
Inside your add function, you be able to create a sum of every parameter using the arguments keyword:
function add() {
var returnValue = 0;
for (i = 0; i < arguments.length; i++) {
returnValue += arguments[i];
}
return returnValue;
}
The second set of parenthesis will be applied on the value (or object) returned by your function. add(2)(8) would be the same as writing 2(8), which doesn't make sense.

8 millions iterations over 700ms in JS is okay? How to speed up? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I have a game and initializing a map 2000 x 4000 blocks.
It runs only once onLoad and takes ~700ms. How can I speed it up? Other logic depends on this map.
Here is the code:
var start = new Date();
var g = {};
g.world = { h:2000, w:4000, cellInfo: [] };
var i, j,
world = g.world,
hlim = world.h,
wlim = world.w,
cellInfo = world.cellInfo;
for ( i = hlim; i; i--) {
cellInfo[i] = [];
for (j = wlim; j; j--) {
cellInfo[i][j] = 1;
}
}
g.world.cellInfo = cellInfo;
alert(new Date() - start);​
Here is fiddle: http://jsfiddle.net/NSX9z/
A couple of options for you:
Lazy init
Your best bet for speeding it up is to use lazy initialization instead. E.g., instead of initializing all 8 million slots, have the code the relies on them handle it if they're not there. E.g., to get a cell
function getCell(x, y) {
var row, cell;
row = cellInfo[x];
if (!row) {
row = cellInfo[x] = [];
}
cell = row[y];
if (typeof cell === "undefined") {
cell = row[y] = 1; // 1 appears to be the default value
}
return cell;
}
...and similar for setCell. That spreads out the init. Of course, it means things are slightly slower, though it's unlikely to be a perceptible difference.
Array cloning
If you don't do that, another option is to create the 4,000-slot array once, then clone it rather than creating it by hand, in hopes that doing the work inside the JavaScript engine is faster than doing the actual loop yourself:
// ...
var the4k = [];
// ...build it...
// Now use it for one row and clone it for the others
cellInfo[hlim] = the4k;
for ( i = hlim - 1; i; i--) {
cellInfo[i] = the4k.slice(0);
}
Array cloning speeds things up dramatically for me, Chrome goes from ~780ms to ~130ms, IE9 from ~530ms to ~50ms.
The other issue to consider is that on IE8 and earlier, the "slow script warning" isn't based on time, but on number of operations. Your fiddle gives me the slow script warning on IE8. Mine doesn't.
IE8 argues for lazy-init, though, as it takes nearly 9 seconds to run even my version of the fiddle.

Undefined var error in an array iteration on a page using mootools [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
var makeModelYearSelect = document.getElementById("<%= MakeModelYearFilterLB.ClientID %>").control;
var selectedMakeModelYearItems = makeModelYearSelect.get_checkedItems();
var selectedMakeModelYearItemIds = [];
for (var index = 0; index < selectedMakeModelYearItems.length; index++) {
selectedMakeModelYearItemIds.push(selectedMakeModelYearItem[index].get_value(index));
}
Why is this firing back an error of Microsoft JScript runtime error: 'selectedMakeModelYearItem' is undefined?
Mootools won't let me use a simple for...in for iterations.
I've looked at it 6 ways to Sunday so what the heck am I missing?
Because selectedMakeModelYearItem is undefined.
selectedMakeModelYearItems isn't, though.
Maybe you try to call this code berofe page is loaded. In this case select tag that you try to access don't rendered and cannot be accessed from JavaScript. You can try something like
window.addEventListener("load",
(function() {
return function setMakeModelYearFilter() {
var makeModelYearSelect = document.getElementById("<%= MakeModelYearFilterLB.ClientID %>").control;
var selectedMakeModelYearItems = makeModelYearSelect.get_checkedItems();
var selectedMakeModelYearItemIds = [];
for (var index = 0; index < selectedMakeModelYearItems.length; index++) {
selectedMakeModelYearItemIds.push(selectedMakeModelYearItem[index].get_value(index));
}
window.removeEventListener('load', setMakeModelYearFilter, false);
}})()
, false);

What happens in the execution context when this script is executed [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
When i execute the following script the alert statement is printing the function why is it so?
What happens in the execution context? Why the variable basicPattern's undefined value is not printing?
function basicPattern(){
var o = 5;
return o;
}
var basicPattern;
console.log(basicPattern);
function basicPattern(){
var o = 5;
return o;
}
var basicPattern;
console.log(basicPattern);
Evaluates same as this (IE bugs disregarded):
var basicPattern;
basicPattern = function basicPattern(){
var o = 5;
return o;
};
console.log(basicPattern);
Since basicPattern was already declared, declaring it again won't have any effect since declarations
are hoisted and merged. If you had assignment to 5 it would go like this:
var basicPattern;
basicPattern = function basicPattern(){
var o = 5;
return o;
};
basicPattern = 5;
console.log(basicPattern);
Read more about hoisting: http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

What is the best way to call a function that receives single objects as argument when you have collections instead? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
Sometimes you have a function that will work for flat arguments. For example:
send(player,message)
But what if, instead, you have collections of players / messages?
message = ['Welcome!','Check our site for events.']
players = [Player1,Player2,Player3]
Writting for-loops will reduce readability and won't work if you don't know statically if your argument is a collection or object. Rewritting the function is sometimes not viable or too laborous and promotes duplicate code. What is a simplier solution?
You can write a decorator that will transform your function into a function that will take the cartesian product of it's own arguments and call the original function on it.
function send(player,message) {
console.log('To ',player,': ',message);
}
cartesian(send)(['Player1','Player2','Player3'],['Welcome!','Check our site.']);
//Output:
//To Player1 : Welcome!
//To Player1 : Check our site.
//To Player2 : Welcome!
//To Player2 : Check our site.
//To Player3 : Welcome!
//To Player3 : Check our site.
This implements the decorator ("cartesian") on Javascript:
function cartesian_product(arr){
//cartesian_product( [[1,2],[3,4]] ) = [[1,3],[1,3],[2,3],[2,4]]
function partial_product(arr,i){
//partial_product([[1,2],3],0) = [[1,3],[2,3]]
var result = []
for (j=0; j<arr[i].length; ++j){
arr_changed = arr.slice();
arr_changed.splice(i,1,arr[i][j]);
result.push(arr_changed);
};
return result;
};
var result = [arr.slice()];
for (var x=0; x<arr.length; ++x){
for (var y=0; y<result.length; ++y){
if (result[y][x] instanceof Array) {
result.splice.apply(result,[y,1].concat(partial_product(result[y],x)));
}
}
}
return result;
};
function cartesian(func){
//cartesian(func)([1,2],[3,4]) = [func([1,3]),func([1,4]),func([2,3]),func([2,4])]
_this = this;
return function(){
var args_list = cartesian_product(Array.prototype.slice.call(arguments));
var return_values = []
for (var i=0; i<args_list.length; ++i){
return_values.push(func.apply(_this,args_list[i]))
}
return return_values;
}
}

Categories

Resources